diff options
author | 2020-04-18 02:38:35 +0200 | |
---|---|---|
committer | 2020-04-18 02:50:54 +0200 | |
commit | 35a41e63ebd5f6cf9d17419c150eb53a005d2e87 (patch) | |
tree | e0bcc21bbb1e7e200857cfbd52acb82b008a3a6d /web | |
parent | Display version and last update in the footer (diff) | |
download | glsamaker-35a41e63ebd5f6cf9d17419c150eb53a005d2e87.tar.gz glsamaker-35a41e63ebd5f6cf9d17419c150eb53a005d2e87.tar.bz2 glsamaker-35a41e63ebd5f6cf9d17419c150eb53a005d2e87.zip |
Add the initial version of the rewritten glsamaker
The glsamaker has been completly rewritten in go. It is
using postgres instead of mysql now. The look and feel is
based on tyrian.
Signed-off-by: Max Magorsch <arzano@gentoo.org>
Diffstat (limited to 'web')
52 files changed, 5830 insertions, 0 deletions
diff --git a/web/packs/account.js b/web/packs/account.js new file mode 100644 index 0000000..a9825fb --- /dev/null +++ b/web/packs/account.js @@ -0,0 +1,81 @@ + +// Base64 to ArrayBuffer +function bufferDecode(value) { + return Uint8Array.from(atob(value), c => c.charCodeAt(0)); +} + +// ArrayBuffer to URLBase64 +function bufferEncode(value) { + return btoa(String.fromCharCode.apply(null, new Uint8Array(value))) + .replace(/\+/g, "-") + .replace(/\//g, "_") + .replace(/=/g, "");; +} + +function registerUser() { + + authname = $("#webauthn-name").val(); + authname = authname.substring(0, 20); + authname = escape(authname); + + $.get( + '/account/2fa/webauthn/register/begin', + null, + function (data) { + return data + }, + 'json') + .then((credentialCreationOptions) => { + console.log(credentialCreationOptions) + credentialCreationOptions.publicKey.challenge = bufferDecode(credentialCreationOptions.publicKey.challenge); + credentialCreationOptions.publicKey.user.id = bufferDecode(credentialCreationOptions.publicKey.user.id); + if (credentialCreationOptions.publicKey.excludeCredentials) { + for (var i = 0; i < credentialCreationOptions.publicKey.excludeCredentials.length; i++) { + credentialCreationOptions.publicKey.excludeCredentials[i].id = bufferDecode(credentialCreationOptions.publicKey.excludeCredentials[i].id); + } + } + + return navigator.credentials.create({ + publicKey: credentialCreationOptions.publicKey + }) + }) + .then((credential) => { + console.log(credential) + let attestationObject = credential.response.attestationObject; + let clientDataJSON = credential.response.clientDataJSON; + let rawId = credential.rawId; + + $.post( + '/account/2fa/webauthn/register/finish?name=' + authname, + JSON.stringify({ + id: credential.id, + rawId: bufferEncode(rawId), + type: credential.type, + response: { + attestationObject: bufferEncode(attestationObject), + clientDataJSON: bufferEncode(clientDataJSON), + }, + }), + function (data) { + return data + }, + 'json') + }) + .then((success) => { + // successfully registered + return + }) + .catch((error) => { + // failed to register + console.log(error) + }) +} + + +$( "#register-webauthn" ).click(function() { + if($("#webauthn-name").val().length == 0){ + alert("Please provide a non-empty Authenticator Name"); + }else{ + registerUser(); + } +}); diff --git a/web/packs/admin.js b/web/packs/admin.js new file mode 100644 index 0000000..f536b42 --- /dev/null +++ b/web/packs/admin.js @@ -0,0 +1,60 @@ + +$( "#addUser" ).click(function() { + + if($("#newNick").val() == "" || $("#newName").val() == "" || $("#newEmail").val() == ""){ + if($("#newNick").val() == ""){ + $("#newNick").addClass("is-invalid"); + } + if($("#newName").val() == ""){ + $("#newName").addClass("is-invalid"); + } + if($("#newEmail").val() == ""){ + $("#newEmail").addClass("is-invalid"); + } + return; + } + + var newNick = $("#newNick").val(); + var newName = $("#newName").val(); + var newEmail = $("#newEmail").val(); + + var newUser = '<tr>\n' + + ' <td>\n' + + ' <span class="my-1 badge badge-secondary float-left mr-2" style="background: none;border: 1px solid grey;">\n' + + ' <i class="fa fa-user mr-1" aria-hidden="true" style="font-size: 0.8rem;color: grey;"></i>\n' + + ' <span class="text-uppercase" style="color:grey;">User</span>\n' + + ' </span>\n' + + ' </td>\n' + + ' <td>\n' + + ' <input name="userId" type="text" value="-1" hidden/>\n' + + ' <input name="userNick" class="form-control form-control-sm" value="' + newNick + '" style="max-width: 150px;"/>\n' + + ' </td>\n' + + ' <td>\n' + + ' <input name="userName" class="form-control form-control-sm" value="' + newName + '" style="max-width: 150px;"/>\n' + + ' </td>\n' + + ' <td>\n' + + ' <input name="userEmail" class="form-control form-control-sm" value="' + newEmail + '" style="max-width: 150px;"/>\n' + + ' </td>\n' + + ' <td>\n' + + ' <i class="my-2 fa fa-times" style="color: darkred;" aria-hidden="true"></i>\n' + + ' </td>\n' + + ' <td>\n' + + ' <i class="my-2 fa fa-times" style="color: darkred;" aria-hidden="true"></i>\n' + + ' </td>\n' + + ' <td>\n' + + ' <i class="my-2 ml-2 fa fa-check" style="color: green;" aria-hidden="true"></i>\n' + + ' </td>\n' + + ' <td>\n' + + ' <input name="userForce2FA" class="m-2" type="checkbox" value="-1" />\n' + + ' </td>\n' + + ' <td>\n' + + ' <input name="userActive" class="m-2" type="checkbox" value="-1" checked/>\n' + + ' </td>\n' + + ' <td>\n' + + ' <button type="button" class="float-right my-1 py-0 btn btn-outline-secondary btn-sm">Actions</button>\n' + + ' </td>\n' + + ' </tr>' + + $("#userList").append(newUser); + $("#addUserForm").hide(); +}); diff --git a/web/packs/application.js b/web/packs/application.js new file mode 100644 index 0000000..95200ea --- /dev/null +++ b/web/packs/application.js @@ -0,0 +1,69 @@ +import "core-js/stable"; +import "regenerator-runtime/runtime"; +require("turbolinks").start(); +import 'bootstrap'; + + +window.dataTables = []; +window.RequestsDataTables = []; +window.DraftsDataTables = []; +window.ArchivesDataTables = []; +window.AllDataTables = []; + +require( 'datatables.net' )( window, $ ); +require( 'datatables.net-bs4' )( window, $ ); +require( 'datatables.net-buttons' )( window, $ ); +require( 'datatables.net-buttons-bs4/js/buttons.bootstrap4.min' )( window, $ ); +require('datatables.net-buttons/js/buttons.colVis.js')( window, $ ); + +import requests from './src/javascript/requests'; +import all from './src/javascript/all'; +import drafts from './src/javascript/drafts'; +import archive from './src/javascript/archive'; +import cvetool from './src/javascript/cvetool'; + +document.addEventListener("turbolinks:load", () => { + requests.initDatatable(); + drafts.initDatatable(); + archive.initDatatable(); + cvetool.initDatatable(); + all.initDatatable(); +}); + +document.addEventListener("turbolinks:before-cache", () => { + requests.destroyDatatable(); + drafts.destroyDatatable(); + archive.destroyDatatable(); + cvetool.destroyDatatable(); + all.destroyDatatable(); +}); + + +// double shift press + +var delta = 500; +var lastKeypressTime = 0; +function KeyHandler(event) { + if ( event.ctrlKey ){ + var thisKeypressTime = new Date(); + if ( thisKeypressTime - lastKeypressTime <= delta ) { + doDoubleKeypress(); + thisKeypressTime = 0; + } + lastKeypressTime = thisKeypressTime; + } +} + +function doDoubleKeypress() { + if($('#large-quicksearch').length){ + $('#large-quicksearch').val(''); + $('#large-quicksearch').focus(); + }else if($('#quicksearch').length){ + $('#quicksearch').val(''); + $('#quicksearch').focus(); + } +} + +// keyboard navigation is disabled for now +//document.addEventListener('keydown', KeyHandler); + diff --git a/web/packs/edit.js b/web/packs/edit.js new file mode 100644 index 0000000..7c47dd7 --- /dev/null +++ b/web/packs/edit.js @@ -0,0 +1,235 @@ +function registerDeleteReferenceButtons(){ + $('.btn-delete-reference').on('click', function(event){ + $(this).parent().parent().parent().remove(); + }); +} + +function registerDeleteBugButtons(){ + $('.btn-delete-bug').on('click', function(event){ + $(this).parent().parent().parent().remove(); + }); +} + +function registerDeletePackageButtons(){ + $('.btn-delete-package').on('click', function(event){ + $(this).parent().parent().parent().parent().remove(); + }); +} + +registerDeleteBugButtons(); +registerDeleteReferenceButtons(); +registerDeletePackageButtons(); + +$('.btn-add-bug').on('click', function(event){ + + var newBugId = $("#new_bug_id").val(); + + if(newBugId == "") { + return; + } + + var newBug = '<div class="col-sm-12 mt-2">' + + '<div class="row" style="margin-bottom:2px;">' + + '<div class="col-md-auto align-h-right" style="padding-right:0px;color:#505050;">' + + '<small style="font-size: 12px;">' + + '<small style="font-size: 12px;">' + + '<input name="bugs" class="form-control" type="text" value="' + newBugId + '" style="max-width: 75px;height: 30px;padding: .25rem .5rem;display: inline-block" />' + + '</small>' + + '</small>' + + '</div>' + + '<div class="col py-1" style="color:#292929;padding-left:10px;">' + + '<small style="font-size: 12px;">TODO...</small>' + + '</div>' + + '<small style="font-size: 12px;margin-top: 2px;">' + + '<button type="button" class="btn btn-outline-danger mr-3 py-0 btn-delete-bug" type="text" style="height: 25px;display: inline-block">Delete</button>' + + '</small>' + + '</div>' + + '</div>'; + + $("#bugs-list").append(newBug); + + registerDeleteBugButtons(); +}); + + +$('.btn-add-reference').on('click', function(event){ + + var newReferenceTitle = $("#new_reference_title").val(); + var newReferenceURL = $("#new_reference_url").val(); + + if(newReferenceTitle == "" || newReferenceURL == "") { + return; + } + + var newReference = '<div class="col-sm-12 mt-2">' + + '<div class="row" style="margin-bottom:2px;">' + + '<div class="col-md-auto align-h-right" style="padding-right:0px;color:#505050;">' + + '<small style="font-size: 12px;">' + + '<small style="font-size: 12px;">' + + '<input name="reference_title" class="form-control" type="text" value="' + newReferenceTitle + '" style="max-width: 125px;height: 30px;padding: .25rem .5rem;display: inline-block" />' + + '</small>' + + '</small>' + + '</div>' + + '<div class="col" style="color:#292929;padding-left:10px;">' + + '<small style="font-size: 12px;">' + + '<input name="reference_url" class="form-control" type="text" value="' + newReferenceURL + '" style="height: 30px;padding: .25rem .5rem;display: inline-block" />' + + '</small>' + + '</div>' + + '<small style="font-size: 12px;margin-top: 2px;">' + + '<button type="button" class="btn btn-outline-danger btn-delete-reference mr-3 py-0" type="text" style="height: 25px;display: inline-block">Delete</button>' + + '</small>' + + '</div>' + + '</div>'; + + $("#reference_list").append(newReference); + + registerDeleteReferenceButtons(); +}); + + +$('.btn-add-vulnerable-package').on('click', function(event){ + + var addVulnerablePackageId = $("#add-vulnerable-package-atom").val(); + var addVulnerablePackageIdentifier = $("#add-vulnerable-package-identifier").val(); + var addVulnerablePackageVersion = $("#add-vulnerable-package-version").val(); + var addVulnerablePackageSlot = $("#add-vulnerable-package-slot").val(); + var addVulnerablePackageArch = $("#add-vulnerable-package-arch").val(); + var addVulnerablePackageAuto = $("#add-vulnerable-package-auto").val(); + + if(addVulnerablePackageId == "" || addVulnerablePackageIdentifier == "" || addVulnerablePackageVersion == "" || addVulnerablePackageSlot == "" || addVulnerablePackageArch == "" || addVulnerablePackageAuto == "") { + return; + } + + var newPackage = '<div class="col-12 mt-2">' + + '<div class="row">' + + '<div class="col-md-auto" style="color:#292929;">' + + '<small style="font-size: 12px;">' + + '<input name="package_vulnerable" value="true" hidden />' + + '<input name="package_atom" class="form-control" type="text" value="' + addVulnerablePackageId + '" style="width:150px; height: 30px;padding: .25rem .5rem;display: inline-block" />' + + '</small>' + + '</div>' + + '<div class="col-md-auto pl-0" style="color:#292929;">' + + '<small style="font-size: 12px;">' + + '<select name="package_identifier" class="custom-select" style="display: inline-block;max-width: 100px;height: 30px;padding: .25rem .5rem;">' + + '<option value=">=" ' + (addVulnerablePackageIdentifier == ">=" ? 'selected' : '') + '>>=</option>' + + '<option value=">" ' + (addVulnerablePackageIdentifier == ">" ? 'selected' : '') + '>> </option>' + + '<option value="*>=" ' + (addVulnerablePackageIdentifier == "*>=" ? 'selected' : '') + '>*>= </option>' + + '<option value="*>" ' + (addVulnerablePackageIdentifier == "*>" ? 'selected' : '') + '>*> </option>' + + '<option value="<=" ' + (addVulnerablePackageIdentifier == "<=" ? 'selected' : '') + '><= </option>' + + '<option value="<" ' + (addVulnerablePackageIdentifier == "<" ? 'selected' : '') + '>< </option>' + + '<option value="*<=" ' + (addVulnerablePackageIdentifier == "*<=" ? 'selected' : '') + '>*<= </option>' + + '<option value="*<" ' + (addVulnerablePackageIdentifier == "*<" ? 'selected' : '') + '>*< </option>' + + '<option value="=" ' + (addVulnerablePackageIdentifier == "=" ? 'selected' : '') + '>= </option>' + + '</select>' + + '</small>' + + '</div>' + + '<div class="col-md-auto pl-0" style="color:#292929;">' + + '<small style="font-size: 12px;">' + + '<input name="package_version" class="form-control" type="text" value="' + addVulnerablePackageVersion + '" style="width: 80px; height: 30px;padding: .25rem .5rem;display: inline-block" />' + + '</small>' + + '</div>' + + '<div class="col-md-auto pl-0" style="color:#292929;">' + + '<small style="font-size: 12px;">' + + '<input name="package_slot" class="form-control" type="text" value="' + addVulnerablePackageSlot + '" style="width: 30px; height: 30px;padding: .25rem .5rem;display: inline-block" />' + + '</small>' + + '</div>' + + '<div class="col-md-auto pl-0" style="color:#292929;">' + + '<small style="font-size: 12px;">' + + '<input name="package_arch" class="form-control" type="text" value="' + addVulnerablePackageArch + '" style="width: 30px; height: 30px;padding: .25rem .5rem;display: inline-block" />' + + '</small>' + + '</div>' + + '<div class="col-md-auto pl-0" style="color:#292929;">' + + '<small style="font-size: 12px;">' + + '<select name="package_auto" class="custom-select" id="inputGroupSelect01" style="display: inline-block;max-width: 100px;height: 30px;padding: .25rem .5rem;">' + + '<option value="yes" ' + (addVulnerablePackageAuto == "true" ? 'selected' : '') + '>yes </option>' + + '<option value="no" ' + (addVulnerablePackageAuto == "false" ? 'selected' : '') + '>no</option>' + + '</select>' + + '</small>' + + '</div>' + + '<div class="col-md-auto pl-0" style="color:#292929;">' + + '<small style="font-size: 12px;">' + + '<button type="button" class="btn btn-outline-danger btn-delete-package" type="text" placeholder="*" style="width: 30px; height: 30px;padding: .25rem .5rem;display: inline-block">-</button>' + + '</small>' + + '</div>' + + '</div>' + + '</div>'; + + $("#vulnerable_package_list").append(newPackage); + + registerDeletePackageButtons(); +}); + + + +$('.btn-add-unaffected-package').on('click', function(event){ + + var addVulnerablePackageId = $("#add-unaffected-package-atom").val(); + var addVulnerablePackageIdentifier = $("#add-unaffected-package-identifier").val(); + var addVulnerablePackageVersion = $("#add-unaffected-package-version").val(); + var addVulnerablePackageSlot = $("#add-unaffected-package-slot").val(); + var addVulnerablePackageArch = $("#add-unaffected-package-arch").val(); + var addVulnerablePackageAuto = $("#add-unaffected-package-auto").val(); + + if(addVulnerablePackageId == "" || addVulnerablePackageIdentifier == "" || addVulnerablePackageVersion == "" || addVulnerablePackageSlot == "" || addVulnerablePackageArch == "" || addVulnerablePackageAuto == "") { + return; + } + + var newPackage = '<div class="col-12 mt-2">' + + '<div class="row">' + + '<div class="col-md-auto" style="color:#292929;">' + + '<small style="font-size: 12px;">' + + '<input name="package_vulnerable" value="false" hidden />' + + '<input name="package_atom" class="form-control" type="text" value="' + addVulnerablePackageId + '" style="width:150px; height: 30px;padding: .25rem .5rem;display: inline-block" />' + + '</small>' + + '</div>' + + '<div class="col-md-auto pl-0" style="color:#292929;">' + + '<small style="font-size: 12px;">' + + '<select name="package_identifier" class="custom-select" style="display: inline-block;max-width: 100px;height: 30px;padding: .25rem .5rem;">' + + '<option value=">=" ' + (addVulnerablePackageIdentifier == ">=" ? 'selected' : '') + '>>=</option>' + + '<option value=">" ' + (addVulnerablePackageIdentifier == ">" ? 'selected' : '') + '>> </option>' + + '<option value="*>=" ' + (addVulnerablePackageIdentifier == "*>=" ? 'selected' : '') + '>*>= </option>' + + '<option value="*>" ' + (addVulnerablePackageIdentifier == "*>" ? 'selected' : '') + '>*> </option>' + + '<option value="<=" ' + (addVulnerablePackageIdentifier == "<=" ? 'selected' : '') + '><= </option>' + + '<option value="<" ' + (addVulnerablePackageIdentifier == "<" ? 'selected' : '') + '>< </option>' + + '<option value="*<=" ' + (addVulnerablePackageIdentifier == "*<=" ? 'selected' : '') + '>*<= </option>' + + '<option value="*<" ' + (addVulnerablePackageIdentifier == "*<" ? 'selected' : '') + '>*< </option>' + + '<option value="=" ' + (addVulnerablePackageIdentifier == "=" ? 'selected' : '') + '>= </option>' + + '</select>' + + '</small>' + + '</div>' + + '<div class="col-md-auto pl-0" style="color:#292929;">' + + '<small style="font-size: 12px;">' + + '<input name="package_version" class="form-control" type="text" value="' + addVulnerablePackageVersion + '" style="width: 80px; height: 30px;padding: .25rem .5rem;display: inline-block" />' + + '</small>' + + '</div>' + + '<div class="col-md-auto pl-0" style="color:#292929;">' + + '<small style="font-size: 12px;">' + + '<input name="package_slot" class="form-control" type="text" value="' + addVulnerablePackageSlot + '" style="width: 30px; height: 30px;padding: .25rem .5rem;display: inline-block" />' + + '</small>' + + '</div>' + + '<div class="col-md-auto pl-0" style="color:#292929;">' + + '<small style="font-size: 12px;">' + + '<input name="package_arch" class="form-control" type="text" value="' + addVulnerablePackageArch + '" style="width: 30px; height: 30px;padding: .25rem .5rem;display: inline-block" />' + + '</small>' + + '</div>' + + '<div class="col-md-auto pl-0" style="color:#292929;">' + + '<small style="font-size: 12px;">' + + '<select name="package_auto" class="custom-select" id="inputGroupSelect01" style="display: inline-block;max-width: 100px;height: 30px;padding: .25rem .5rem;">' + + '<option value="yes" ' + (addVulnerablePackageAuto == "true" ? 'selected' : '') + '>yes </option>' + + '<option value="no" ' + (addVulnerablePackageAuto == "false" ? 'selected' : '') + '>no</option>' + + '</select>' + + '</small>' + + '</div>' + + '<div class="col-md-auto pl-0" style="color:#292929;">' + + '<small style="font-size: 12px;">' + + '<button type="button" class="btn btn-outline-danger btn-delete-package" type="text" placeholder="*" style="width: 30px; height: 30px;padding: .25rem .5rem;display: inline-block">-</button>' + + '</small>' + + '</div>' + + '</div>' + + '</div>'; + + $("#unaffected_package_list").append(newPackage); + + registerDeletePackageButtons(); +}); + diff --git a/web/packs/glsa.js b/web/packs/glsa.js new file mode 100644 index 0000000..0490db0 --- /dev/null +++ b/web/packs/glsa.js @@ -0,0 +1,114 @@ + +$( "#save-new-glsa-comment" ).click(function() { + var glsaid = $("#glsa-id").html(); + var comment = $('#comment').val(); + $('#comment').val(" "); + $('#comment').focusout(); + + commentGLSA(glsaid, comment, "comment"); + +}); + +$( "#save-new-glsa-approve" ).click(function() { + var glsaid = $("#glsa-id").html(); + var comment = $('#comment').val(); + $('#comment').val(" "); + $('#comment').focusout(); + + commentGLSA(glsaid, comment, "approve"); + +}); + +$( "#save-new-glsa-decline" ).click(function() { + var glsaid = $("#glsa-id").html(); + var comment = $('#comment').val(); + $('#comment').val(" "); + $('#comment').focusout(); + + commentGLSA(glsaid, comment, "decline"); + +}); + +function commentGLSA(glsaid, comment, commentType){ + + $.post( + '/glsa/comment/add', + { + glsaid: glsaid, + comment: comment, + commentType: commentType, + }, + function(data) { + + if(data != "err") { + + + + console.log("hi"); + console.log(data); + var comment = JSON.parse(data); + var commentDate = comment.Date.split("T")[0] + ' ' + comment.Date.split("T")[1].split(".")[0] + ' UTC'; + var background = ""; + var hint = ""; + if(comment.Type == "approve"){ + background = "background:#DFF0D8;"; + hint = '<b class="mr-2">Approved: </b>'; + } else if(comment.Type == "decline"){ + background = "background:#F2DEDE;"; + hint = '<b class="mr-2">Declined: </b>'; + } + + var newComment = '<div class="col-12 mt-3">' + + '<div id="c0" class="card" style="padding:0px;' + background +'">' + + '<div class="card-header" style="' + background + '">' + + '<div class="row">' + + '<div class="col-sm-8">' + + '<div class="row">' + + '<div class="col-sm-12">' + + '<span style="color:#000!important;">' + + '<span class="vcard"><a class="email" href="mailto:' + comment.User + '"> <b class="text-dark">' + comment.User + '</b></a></span>' + + '</span>' + + '<span class="ml-2">' + + '<span class="badge badge-secondary" title="' + comment.UserBadge.Description + '" style="background: none;border: 1px solid ' + comment.UserBadge.Color + ';">' + + '<span class="text-capitalize" style="color: ' + comment.UserBadge.Color + ';">' + comment.UserBadge.Name + '</span>' + + '</span>' + + '</span>' + + '</div>' + + '<div class="col-sm-12">' + + '<span style="color:#505050; font-weight: normal;margin-left:2px;">' + + commentDate + + '</span>' + + '</div>' + + '</div>' + + '</div>' + + '<div class="col-sm-4">' + + '<div>' + + '<a href="#" class="btn btn-default btn-xs float-right" style="background:transparent;color:#505050;border:none;"><i class="fa fa-compress" aria-hidden="true"></i></a>' + + '<a class="btn btn-default btn-xs float-right" href="#add_comment" style="background:transparent;color:#505050;border:none;"><i class="fa fa-reply" aria-hidden="true"></i></a>' + + '<a href="#" class="btn btn-default btn-xs float-right" style="background:transparent;color:#505050;border:none;"><i class="fa fa-tag" aria-hidden="true"></i></a>' + + '</div>' + + '</div>' + + '</div>' + + '</div>' + + '<div class="card-body">' + + hint + + comment.Message + + '</div>' + + '</div>' + + '</div>'; + + $('#comments-section').append(newComment); + + } + return + }); +} + + +$('#btn-delete-glsa').on('click', function(event){ + var glsaid = $("#glsa-id").html(); + $.get( "/glsa/delete/" + glsaid, function( data ) { + document.location.href = "/"; + }); +}); + diff --git a/web/packs/newglsa.js b/web/packs/newglsa.js new file mode 100644 index 0000000..8b15ef8 --- /dev/null +++ b/web/packs/newglsa.js @@ -0,0 +1,58 @@ + +var BUGZILLA_URL = 'https://bugs.gentoo.org'; + +$( "#bugs" ).on('textInput input', refreshBugs); + +function refreshBugs(){ + $("#bug-refresh-ok").hide(); + $("#bug-refresh-failed").hide(); + $("#bug-spinner").show(); + + var bugIds = $("#bugs").val(); + + console.log(BUGZILLA_URL + "/rest/bug?id=" + bugIds); + + // validate data + var valid = true; + bugIds.split(",").forEach(function(bugID) { + if( bugIds == "" || isNaN(bugID) || !(bugID.length == 0 || bugID.length == 6 || bugID.length == 7) ){ + $( "#bug-spinner" ).hide(); + $( "#bug-refresh-failed" ).show(); + valid = false; + } + }); + + if(valid){ + $.getJSON( BUGZILLA_URL + "/rest/bug?id=" + bugIds, function( data ) { + + if(data.bugs.length != bugIds.split(",").length){ + $( "#bug-spinner" ).hide(); + $( "#bug-refresh-failed" ).show(); + return + } + + bugReady = true; + title = ""; + data.bugs.forEach(function(bug) { + title = title == "" ? bug.summary : title; + bugReady = bugReady && bug.whiteboard.includes("[glsa"); + }); + + if(bugReady){ + $(".badge-notbugready").hide(); + $(".badge-bugready").show(); + } else { + $(".badge-bugready").hide(); + $(".badge-notbugready").show(); + } + + if($("#title").val() == ""){ + $("#title").val(title); + } + + $("#bug-spinner").hide(); + $("#bug-refresh-ok").show(); + + }); + } +} diff --git a/web/packs/src/javascript/all.js b/web/packs/src/javascript/all.js new file mode 100644 index 0000000..715e472 --- /dev/null +++ b/web/packs/src/javascript/all.js @@ -0,0 +1,37 @@ + +function initDatatable(){ + if (window.AllDataTables.length === 0 && $('.all-data-table').length !== 0) { + $('.all-data-table').each((_, element) => { + + var table = $(element).DataTable( { + "order": [[ 0, "desc" ]], + "paging": true, + "ordering": true, + "searching": true, + "info": true, + "lengthChange": false, + "language": { + "emptyTable": "Currently there are no glsas available. -- Start with filling one." + } + }); + + window.AllDataTables.push(table); + + // Add event listener for opening and closing details + $('#table_id tbody').on('click', 'td', function () { + var tr = $(this).closest('tr'); + var row = table.row( tr ); + Turbolinks.visit("/glsa/" + row.data()[0]); + } ); + + }); + } +} + +function destroyDatatable() { + while (window.AllDataTables.length !== 0) { + window.AllDataTables.pop().destroy(); + } +} + +export default {initDatatable, destroyDatatable} diff --git a/web/packs/src/javascript/archive.js b/web/packs/src/javascript/archive.js new file mode 100644 index 0000000..088aa6b --- /dev/null +++ b/web/packs/src/javascript/archive.js @@ -0,0 +1,42 @@ + +function initDatatable(){ + if (window.ArchivesDataTables.length === 0 && $('.archives-data-table').length !== 0) { + $('.archives-data-table').each((_, element) => { + + var table = $(element).DataTable( { + "order": [[ 0, "desc" ]], + "paging": true, + "ordering": true, + "searching": true, + "info": true, + "lengthChange": false, + "language": { + "emptyTable": "Currently there are no GLSAs available. -- Start with releasing one." + }, + "columnDefs": [ + { + "targets": 'hide', + "visible": false + }], + }); + + window.ArchivesDataTables.push(table); + + // Add event listener for opening and closing details + $('#table_id tbody').on('click', 'td', function () { + var tr = $(this).closest('tr'); + var row = table.row( tr ); + Turbolinks.visit("/glsa/" + row.data()[0]); + } ); + + }); + } +} + +function destroyDatatable(){ + while (window.ArchivesDataTables.length !== 0) { + window.ArchivesDataTables.pop().destroy(); + } +} + +export default {initDatatable, destroyDatatable} diff --git a/web/packs/src/javascript/cvetool.js b/web/packs/src/javascript/cvetool.js new file mode 100644 index 0000000..6158714 --- /dev/null +++ b/web/packs/src/javascript/cvetool.js @@ -0,0 +1,535 @@ + +var BUGZILLA_URL = 'https://bugs.gentoo.org'; + + +function destroyDatatable(){ + while (window.dataTables.length !== 0) { + window.dataTables.pop().destroy(); + } +} + + +function initDatatable(){ + if (window.dataTables.length === 0 && $('.data-table').length !== 0) { + $('.data-table').each((_, element) => { + + var table = $(element).DataTable( { + "processing": true, + "serverSide": true, + "ajax": "/cve/data", + "order": [[ 0, "desc" ]], + "columnDefs": [ + { + "render": function ( data, type, row ) { + return '<b>' + data + '</b>' + }, + "targets" : 'render-bold', + }, + { + "render": function ( data, type, row ) { + var bugs = ' <i>no assigned bugs</i>'; + if(data!='' && JSON.parse(data) != null){ + bugs = ""; + JSON.parse(data).forEach(function(bug) { + bugs = bugs + bug.id + ","; + }); + } + return bugs; + }, + "targets" : 'render-bug', + }, + { + "targets" : 'no-sort', + "orderable": false, + }, + { + "render": function ( data, type, row ) { + return renderState(data, row[0]) + }, + "targets" : 'render-state', + }, + { + "render": function ( data, type, row ) { + if(data == "0.0"){ + return '<span class="badge badge-secondary">None</span>' + }else if(parseFloat(data) < 4.0) { + return '<span class="badge badge-success">' + data + '</span>' + }else if(parseFloat(data) < 7.0) { + return '<span class="badge badge-warning">' + data + '</span>' + }else if(parseFloat(data) < 9.0) { + return '<span class="badge badge-danger">' + data + '</span>' + }else if(parseFloat(data) < 10.0) { + return '<span class="badge badge-danger">' + data + '</span>' + } + return + + }, + "targets" : 'render-basescore', + }, + { + "targets": 'hide', + "visible": false + }], + buttons: [ + { + extend: 'colvis', + columns: ':not(.noVis)', + text: 'Columns', + className: 'btn-sm btn-outline-secondary colvis-btn' + }, + { + text: 'Fullscreen', + className: 'btn-sm btn-outline-secondary colvis-btn fullscreen-btn', + action: function ( e, dt, node, config ) { + if(window.location.href.includes("fullscreen")){ + Turbolinks.visit("/cve/tool"); + } else { + Turbolinks.visit("/cve/tool/fullscreen"); + } + } + }, + { + text: 'State', + className: 'btn-sm btn-outline-secondary float-left colvis-btn mr-2 dropdown-toggle view-filter-state' + } + ], + "initComplete": function( settings, json ) { + + $('#table_id_length').append( "<span class='ml-4'> Show </span>" ); + table.buttons().container() + .appendTo( $('#table_id_length') ); + $('.buttons-colvis').removeClass("btn-secondary"); + + $('#table_id_length').append( "<span class='ml-4'> Toggle </span>" ); + $('.fullscreen-btn').appendTo( $('#table_id_length') ); + + + $('#table_id_filter').prepend( '<div id="filterByStateDropdown" class="dropdown"> <div class="dropdown-menu" aria-labelledby="dropdownMenuButton"> <button id="filterByStateNew" class="dropdown-item"><span class="badge badge-danger state">New</span></button> <button id="filterByStateAssigned" class="dropdown-item"><span class="badge badge-success state">Assigned</span></button> <button id="filterByStateNFU" class="dropdown-item"><span class="badge badge-info state">NFU</span></button> <button id="filterByStateLater" class="dropdown-item"><span class="badge badge-warning state">Later</span></button> <button id="filterByStateInvalid" class="dropdown-item"><span class="badge badge-dark state">Invalid</span></button> <div class="dropdown-divider"></div> <button id="filterByStateAll" class="dropdown-item">All</button> </div> </div>' ); + $('#table_id_filter').prepend( "<span class='m-1 float-left'> Filter by </span>" ); + $('.view-filter-state').prependTo( $('#filterByStateDropdown') ); + document.querySelector(".view-filter-state").setAttribute('data-toggle', 'dropdown'); + + $("#filterByStateNew").on('click', function () { + $('.view-filter-state').text("New"); + table.columns( 10 ).search( "New" ).draw(); + }); + + $("#filterByStateAssigned").on('click', function () { + $('.view-filter-state').text("Assigned"); + table.columns( 10 ).search( "Assigned" ).draw(); + }); + + $("#filterByStateNFU").on('click', function () { + $('.view-filter-state').text("NFU"); + table.columns( 10 ).search( "NFU" ).draw(); + }); + + $("#filterByStateLater").on('click', function () { + $('.view-filter-state').text("Later"); + table.columns( 10 ).search( "Later" ).draw(); + }); + + $("#filterByStateInvalid").on('click', function () { + $('.view-filter-state').text("Invalid"); + table.columns( 10 ).search( "Invalid" ).draw(); + }); + + $("#filterByStateAll").on('click', function () { + $('.view-filter-state').text("State"); + table.columns( 10 ).search( "" ).draw(); + }); + + }, + + }); + + window.dataTables.push(table); + + // Add event listener for opening and closing details + $('#table_id tbody').on('click', 'td', function () { + var tr = $(this).closest('tr'); + var row = table.row( tr ); + + if ( row.child.isShown() ) { + // This row is already open - close it + row.child.hide(); + tr.removeClass('shown'); + } + else { + // Open this row + row.child( format(row.data()) ).show(); + tr.addClass('shown'); + + registerCommentListener(); + + registerAssignBugListener(); + + registerChangeStateListener(); + + } + } ); + + }); + } +} + +function renderState( d, cveid ) { + if(d == "New"){ + return '<span data-cveid="' + cveid + '" class="badge badge-danger state">' + d + '</span>' + }else if(d == "Assigned") { + return '<span data-cveid="' + cveid + '" class="badge badge-success state">' + d + '</span>' + }else if(d == "NFU") { + return '<span data-cveid="' + cveid + '" class="badge badge-info state">' + d + '</span>' + }else if(d == "Later") { + return '<span data-cveid="' + cveid + '" class="badge badge-warning state">' + d + '</span>' + }else if(d == "Invalid") { + return '<span data-cveid="' + cveid + '" class="badge badge-dark state">' + d + '</span>' + }else{ + return '<span data-cveid="' + cveid + '" class="badge badge-primary state">' + d + '</span>' + } + return d +} + +function format ( d ) { + + var bugs = ' <i>no assigned bugs</i>'; + if(d[3]!='' && JSON.parse(d[3]) != null){ + + bugs = ""; + + JSON.parse(d[3]).forEach(function(bug) { + bugs = bugs + bug.id + ","; + }); + + } + + var packages = ' <i>no assigned packages</i>'; + if(d[2]!=''){ + packages = d[2]; + } + + var comments = '<div class="col-12 text-center mb-3"> <i>- no comments yet -</i> </div>'; + if(d[7]!='null') { + console.log("CommentsObject"); + console.log(d[7]); + console.log(JSON.parse(d[7])); + + var commentsObjects = JSON.parse(d[7]); + comments = ''; + commentsObjects.forEach(function (comment, index) { + var commentDate = '<small class="text-muted">' + comment.Date.split("T")[0] + ' ' + comment.Date.split("T")[1].split(".")[0] + ' UTC</small>'; + comments = comments + '<div class="col-3 text-right mb-3"><b>' + comment.User + '</b><br/>' + commentDate + '</div><div class="col-9 mb-3"><div class="card" style="background: none;"><div class="card-body">' + comment.Message + '</div></div></div>'; + }); + } + + var bugs_cards = '<div class="col-12 text-center mb-3"> <i>- no assigned bugs yet -</i> </div>'; + if(d[3]!='' && JSON.parse(d[3]) != null) { + + bugs_cards = ''; + + JSON.parse(d[3]).forEach(function(bug) { + var newBug = '<div class="col-3 text-right mb-3"><b> Bug ' + bug.id + '</b></div><div class="col-9 mb-3"><div class="card" style="background: none;"><div class="card-body pt-2"><span class="bug-title" data-cveid="' + d[0] + '" data-bugid="' + bug.id + '">' + escapeHtml(bug.summary) + '</span><div class="row"><div class="col-6"><small>Alias: </small><small class="bug-alias" data-cveid="' + d[0] + '" data-bugid="' + bug.id + '">' + bug.alias.join(", ") + '</small><br/><small>Status: </small><small class="bug-status" data-cveid="' + d[0] + '" data-bugid="' + bug.id + '">' + escapeHtml(bug.status) + '</small></div><div class="col-6"><small>Whiteboard: </small><small class="bug-whiteboard" data-cveid="' + d[0] + '" data-bugid="' + bug.id + '">' + escapeHtml(bug.whiteboard) + '</small><br/><small>Created: </small><small class="bug-created" data-cveid="' + d[0] + '" data-bugid="' + bug.id + '">' + escapeHtml(bug.creation_time) + '</small></div></div></div></div></div>'; + bugs_cards = bugs_cards + newBug; + }); + + } + + var changes = '<i>no changes yet</i>'; + + // `d` is the original data object for the row + return '<div class="container px-0">' + + '<div class="row py-2">' + + '<div class="col-7"><h4><b>Details of ' + d[0] + '</b></h4></div><div class="col-5"></div>' + + '<div class="col-7">' + + '<span>' + d[1] + '</span>' + + '<div data-cveid="' + d[0] + '" class="row bugs-section mt-4">' + + bugs_cards + + '</div>' + + '<div data-cveid="' + d[0] + '" class="row new-bug-row" style="display: none;">' + + '<div class="col-3 text-right"><b>New Bug</b></div>'+ + '<div class="col-9"><textarea data-cveid="' + d[0] + '" class="form-control new-bug" id="exampleFormControlTextarea1" rows="3" placeholder="Add a bug to ' + d[0] + '"></textarea></div>'+ + '<div class="col-12 mt-2 mb-3"><button data-cveid="' + d[0] + '" type="button" class="btn-save-new-bug float-right btn btn-sm btn-outline-success">Save</button><button data-cveid="' + d[0] + '" type="button" class="mr-2 float-right btn btn-sm btn-outline-danger btn-cancel-new-bug">Cancel</button></div>' + + '</div>'+ + '<div data-cveid="' + d[0] + '" class="row assign-bug-row" style="display: none;">' + + '<div class="col-3 text-right"><b>Assign Bug</b></div>'+ + '<div class="col-9"><input type="text" data-cveid="' + d[0] + '" class="form-control assign-bug" maxlength="6" placeholder="Bug ID"/></div>'+ + '<div class="col-12 mt-2 mb-3"><button data-cveid="' + d[0] + '" type="button" class="btn-save-assign-bug float-right btn btn-sm btn-outline-success">Save</button><button data-cveid="' + d[0] + '" type="button" class="mr-2 float-right btn btn-sm btn-outline-danger btn-cancel-assign-bug">Cancel</button></div>' + + '</div>'+ + '<div class="row pb-4">' + + (window.userCanAssignBug ? '<div class="col-12 mb-3"><button type="button" data-cveid="' + d[0] + '" class="trigger-assign-bug float-right btn btn-sm btn-outline-primary">Assign Bug</button><button type="button" data-cveid="' + d[0] + '" class="trigger-new-bug mr-2 float-right btn btn-sm btn-outline-primary" disabled>Create New Bug</button></div>' : '') + + '</div>'+ + // '<hr/>' + + '<div data-cveid="' + d[0] + '" class="row comments-section pb-1 mt-4">' + + // '<div class="col-12 mb-2"><b>Comments</b></div>' + + comments + + '</div>' + + '<div data-cveid="' + d[0] + '" class="row new-comment-row" style="display: none;">' + + '<div class="col-3 text-right"><b>New Comment</b></div>'+ + '<div class="col-9"><textarea data-cveid="' + d[0] + '" class="form-control new-comment" id="exampleFormControlTextarea1" rows="3" placeholder="Add a comment to ' + d[0] + '"></textarea></div>'+ + '<div class="col-12 mt-2 mb-3"><button data-cveid="' + d[0] + '" type="button" class="save-new-comment float-right btn btn-sm btn-outline-success">Save</button><button data-cveid="' + d[0] + '" type="button" class="mr-2 float-right btn btn-sm btn-outline-danger btn-cancel-comment">Cancel</button></div>' + + '</div>'+ + '<div class="row pb-4">' + + (window.userCanComment ? '<div class="col-12 mb-3"><button type="button" data-cveid="' + d[0] + '" class="trigger-new-comment float-right btn btn-sm btn-outline-primary">Add New Comment</button></div>' : '') + + '</div>'+ + '</div>'+ + '<div class="col-5">' + + '<table class="w-100 float-right" cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">'+ + '<tr><td><b>State:</b></td><td>'+ renderState(d[10], d[0]) + ( (window.userCanChangeState && d[10] != 'Assigned') ? '<div style="display: inline-block;" class="float-right"><a class="btn btn-sm btn-link p-0" data-toggle="collapse" href="#collapseExample-' + d[0] + '" role="button" aria-expanded="false" aria-controls="collapseExample"> change </a></div>' : '') + '</td></tr>'+ + '<tr><td data-cveid="' + d[0] + '" class="change-state-form collapse" id="collapseExample-' + d[0] +'" colspan="2" style="border-top: none;"><div class="row"><div class="col-7"><input data-cveid="' + d[0] + '" class="change-state-reason form-control form-control-sm" type="text" placeholder="reason (required)" /></div> <div class="col-5"> <button data-cveid="' + d[0] + '" type="button" class="change-state-invalid my-1 btn btn-sm btn-outline-dark float-right mr-2 py-0 px-1">Invalid</button> <button data-cveid="' + d[0] + '" type="button" class="change-state-later my-1 btn btn-sm btn-outline-warning float-right mr-2 py-0 px-1">Later</button> <button data-cveid="' + d[0] + '" type="button" class="change-state-nfu my-1 btn btn-sm btn-outline-info float-right mr-2 py-0 px-1">NFU</button></div></div> </td></tr>' + + '<tr><td><b>Last Modified:</b></td><td>'+ d[8] + '</td></tr>'+ + '<tr><td><b>Published:</b></td><td>'+ d[9] + '</td></tr>'+ + '<tr><td><b>Base Score:</b></td><td>'+ d[4] + '</td></tr>'+ + '<tr><td><b>Impact:</b></td><td>'+ d[5] + '</td></tr>'+ + '<tr><td><b>Bug(s):</b></td><td>'+ bugs + '</td></tr>'+ + '<tr><td><b>Package(s):</b></td><td>'+ packages + '</td></tr>'+ + '<tr><td><b>Reference(s):</b></td><td>'+ d[6] + '</td></tr>'+ + // '<tr><td><b>Comments:</b></td><td>'+ d[7] + '</td></tr>'+ + // '<tr><td><b>Changelog:</b></td><td>'+ changes + '</td></tr>'+ + '</table>'+ + '</div>'+ + '</div>'+ + '</div>'; +} + + +$( "#disable-twofactor-notice" ).click(function() { + $("#twofactor-notice").hide(); + $.get( "/account/2fa/notice/disable", function( data ) { + console.log("Disabled 2FA Notice.") + }); +}); + + +function registerCommentListener(){ + + $( ".trigger-new-comment" ).click(function() { + $('.new-comment-row[data-cveid="' + $(this).data( "cveid" ) + '"]').show(); + $('.trigger-new-comment[data-cveid="' + $(this).data( "cveid" ) + '"]').hide(); + }); + + $( ".btn-cancel-comment" ).click(function() { + $('.new-comment-row[data-cveid="' + $(this).data( "cveid" ) + '"]').hide(); + $('.trigger-new-comment[data-cveid="' + $(this).data( "cveid" ) + '"]').show(); + }); + + $( ".save-new-comment" ).click(function() { + var cveid = $(this).data( "cveid" ); + var comment = $('textarea.new-comment[data-cveid="' + cveid + '"]').val(); + console.log('textarea:'); + console.log(); + + + $.post( + '/cve/comment/add', + { + cveid: cveid, + comment: comment, + }, + function(data) { + + if(data != "err") { + console.log("hi"); + console.log(data); + var comment = JSON.parse(data); + var commentDate = '<small class="text-muted">' + comment.Date.split("T")[0] + ' ' + comment.Date.split("T")[1].split(".")[0] + ' UTC</small>'; + var newComment = '<div class="col-3 text-right mb-3"><b>' + comment.User + '</b><br/>' + commentDate + '</div><div class="col-9 mb-3"><div class="card" style="background: none;"><div class="card-body">' + comment.Message + '</div></div></div>'; + $('.comments-section[data-cveid="' + cveid + '"]').append(newComment); + } + return + }); + }); +} + +function registerAssignBugListener(){ + + + $( ".trigger-assign-bug" ).click(function() { + var cveid = $(this).data( "cveid" ); + showAssignBugForm(cveid); + }); + + $( ".btn-cancel-assign-bug" ).click(function() { + var cveid = $(this).data( "cveid" ); + hideAssignBugForm(cveid); + }); + + $( ".btn-save-assign-bug" ).click(function() { + var cveid = $(this).data( "cveid" ); + var bugid = $('input.assign-bug[data-cveid="' + cveid + '"]').val(); + + assignBug(cveid, bugid); + hideAssignBugForm(cveid); + }); +} + +function showAssignBugForm(cveid){ + $('.assign-bug-row[data-cveid="' + cveid + '"]').show(); + $('.trigger-assign-bug[data-cveid="' + cveid + '"]').hide(); + $('.trigger-new-bug[data-cveid="' + cveid + '"]').hide(); +} + +function hideAssignBugForm(cveid) { + $('.assign-bug-row[data-cveid="' + cveid + '"]').hide(); + $('.trigger-assign-bug[data-cveid="' + cveid + '"]').show(); + $('.trigger-new-bug[data-cveid="' + cveid + '"]').show(); +} + + +function assignBug(cveid, bugid){ + + $.post( + '/cve/bug/assign', + { + cveid: cveid, + bugid: bugid, + }, + function(data) { + if(data != "err") { + console.log("hi"); + console.log(data); + + if(data == "ok"){ + + setStateToAssigned(cveid); + + var newBug = '<div class="col-3 text-right mb-3"><b> Bug ' + bugid + '</b></div><div class="col-9 mb-3"><div class="card" style="background: none;"><div class="card-body pt-2"><span class="bug-title" data-cveid="' + cveid + '" data-bugid="' + bugid + '" >Loading...</span><br/><small>Alias: </small><small class="bug-alias" data-cveid="' + cveid + '" data-bugid="' + bugid + '"></small><br/><small>Status: </small><small class="bug-status" data-cveid="' + cveid + '" data-bugid="' + bugid + '"></small><br/><small>Resolution: </small><small class="bug-resolution" data-cveid="' + cveid + '" data-bugid="' + bugid + '"></small><br/><small>Whiteboard: </small><small class="bug-whiteboard" data-cveid="' + cveid + '" data-bugid="' + bugid + '"></small><br/><small>Created: </small><small class="bug-created" data-cveid="' + cveid + '" data-bugid="' + bugid + '"></small><br/><small>Last Update: </small><small class="bug-last-update" data-cveid="' + cveid + '" data-bugid="' + bugid + '"></small></div></div></div>'; + $('.bugs-section[data-cveid="' + cveid + '"]').append(newBug); + + updateBugInformation(cveid, bugid); + } + + } + }); +} + + +function registerChangeStateListener(){ + + $( ".change-state-nfu" ).click(function() { + var cveid = $(this).data( "cveid" ); + var reason = $('.change-state-reason[data-cveid="' + cveid + '"]').val(); + if(reason != "") { + changeState(cveid, reason, "NFU"); + $("#collapseExample-" + cveid).removeClass('show'); + }else{ + $('.change-state-reason[data-cveid="' + cveid + '"]').addClass('is-invalid'); + } + }); + + $( ".change-state-invalid" ).click(function() { + var cveid = $(this).data( "cveid" ); + var reason = $('.change-state-reason[data-cveid="' + cveid + '"]').val(); + if(reason != "") { + changeState(cveid, reason, "Invalid"); + $("#collapseExample-" + cveid).removeClass('show'); + }else{ + $('.change-state-reason[data-cveid="' + cveid + '"]').addClass('is-invalid'); + } + }); + + $( ".change-state-later" ).click(function() { + var cveid = $(this).data( "cveid" ); + var reason = $('.change-state-reason[data-cveid="' + cveid + '"]').val(); + if(reason != ""){ + changeState(cveid, reason, "Later"); + $("#collapseExample-" + cveid).removeClass('show'); + }else{ + $('.change-state-reason[data-cveid="' + cveid + '"]').addClass('is-invalid'); + } + }); +} + +function changeState(cveid, reason, newState){ + + $.post( + '/cve/state/change', + { + cveid: cveid, + newstate: newState, + reason: reason, + }, + function(data) { + if(data != "err") { + console.log("hi"); + console.log(data); + + // change state + setStateTo(cveid, newState); + + // add comment + var comment = JSON.parse(data); + var commentDate = '<small class="text-muted">' + comment.Date.split("T")[0] + ' ' + comment.Date.split("T")[1].split(".")[0] + ' UTC</small>'; + var newComment = '<div class="col-3 text-right mb-3"><b>' + comment.User + '</b><br/>' + commentDate + '</div><div class="col-9 mb-3"><div class="card" style="background: none;"><div class="card-body">' + escapeHtml(comment.Message) + '</div></div></div>'; + $('.comments-section[data-cveid="' + cveid + '"]').append(newComment); + + } + }); +} + + +function setStateToAssigned(cveid) { + setStateTo(cveid, "Assigned"); +} + +function setStateTo(cveid, newState) { + $('.state[data-cveid="' + cveid + '"]').removeClass('badge-primary'); + $('.state[data-cveid="' + cveid + '"]').removeClass('badge-secondary'); + $('.state[data-cveid="' + cveid + '"]').removeClass('badge-success'); + $('.state[data-cveid="' + cveid + '"]').removeClass('badge-danger'); + $('.state[data-cveid="' + cveid + '"]').removeClass('badge-warning'); + $('.state[data-cveid="' + cveid + '"]').removeClass('badge-info'); + $('.state[data-cveid="' + cveid + '"]').removeClass('badge-light'); + $('.state[data-cveid="' + cveid + '"]').removeClass('badge-dark'); + + if(newState == "New"){ + $('.state[data-cveid="' + cveid + '"]').addClass('badge-danger'); + } else if(newState == "Assigned"){ + $('.state[data-cveid="' + cveid + '"]').addClass('badge-success'); + } else if(newState == "NFU"){ + $('.state[data-cveid="' + cveid + '"]').addClass('badge-info'); + } else if(newState == "Later"){ + $('.state[data-cveid="' + cveid + '"]').addClass('badge-warning'); + } else if(newState == "Invalid"){ + $('.state[data-cveid="' + cveid + '"]').addClass('badge-dark'); + } else { + $('.state[data-cveid="' + cveid + '"]').addClass('badge-primary'); + } + + $('.state[data-cveid="' + cveid + '"]').html(newState); +} + + +function updateBugInformation(cveid, bugid){ + $.getJSON( BUGZILLA_URL + "/rest/bug?id=" + bugid, function( data ) { + console.log(data.bugs[0]); + + console.log(escapeHtml(data.bugs[0].alias.join(", "))); + console.log(escapeHtml(data.bugs[0].status)); + console.log(escapeHtml(data.bugs[0].resolution)); + console.log(escapeHtml(data.bugs[0].whiteboard)); + console.log(escapeHtml(data.bugs[0]['creation_time'])); + console.log(escapeHtml(data.bugs[0]['last_change_time'])); + + $('.bug-title[data-cveid="' + cveid + '"][data-bugid="' + bugid + '"]').html(escapeHtml(data.bugs[0].summary)); + + $('.bug-alias[data-cveid="' + cveid + '"][data-bugid="' + bugid + '"]').html('<i>' + escapeHtml(data.bugs[0].alias.join(", ")) + '</i>'); + $('.bug-status[data-cveid="' + cveid + '"][data-bugid="' + bugid + '"]').html('<i>' + escapeHtml(data.bugs[0].status) + '</i>'); + $('.bug-resolution[data-cveid="' + cveid + '"][data-bugid="' + bugid + '"]').html('<i>' + escapeHtml(data.bugs[0].resolution) + '</i>'); + $('.bug-whiteboard[data-cveid="' + cveid + '"][data-bugid="' + bugid + '"]').html('<i>' + escapeHtml(data.bugs[0].whiteboard) + '</i>'); + $('.bug-created[data-cveid="' + cveid + '"][data-bugid="' + bugid + '"]').html('<i>' + escapeHtml(data.bugs[0]['creation_time']) + '</i>'); + $('.bug-last-update[data-cveid="' + cveid + '"][data-bugid="' + bugid + '"]').html('<i>' + escapeHtml(data.bugs[0]['last_change_time']) + '</i>'); + + }); +} + + +function escapeHtml(unsafe) { + return unsafe + .replace(/&/g, "&") + .replace(/</g, "<") + .replace(/>/g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); +} + +export default {initDatatable, destroyDatatable} diff --git a/web/packs/src/javascript/drafts.js b/web/packs/src/javascript/drafts.js new file mode 100644 index 0000000..0430b15 --- /dev/null +++ b/web/packs/src/javascript/drafts.js @@ -0,0 +1,38 @@ + + +function initDatatable(){ + if (window.DraftsDataTables.length === 0 && $('.drafts-data-table').length !== 0) { + $('.drafts-data-table').each((_, element) => { + + var table = $(element).DataTable( { + "order": [[ 0, "desc" ]], + "paging": true, + "ordering": true, + "searching": true, + "info": true, + "lengthChange": false, + "language": { + "emptyTable": "Currently there are no drafts available. -- Start with creating one." + } + }); + + window.DraftsDataTables.push(table); + + // Add event listener for opening and closing details + $('#table_id tbody').on('click', 'td', function () { + var tr = $(this).closest('tr'); + var row = table.row( tr ); + Turbolinks.visit("/glsa/" + row.data()[0]); + } ); + + }); + } +} + +function destroyDatatable(){ + while (window.DraftsDataTables.length !== 0) { + window.DraftsDataTables.pop().destroy(); + } +} + +export default {initDatatable, destroyDatatable} diff --git a/web/packs/src/javascript/requests.js b/web/packs/src/javascript/requests.js new file mode 100644 index 0000000..75a4a6a --- /dev/null +++ b/web/packs/src/javascript/requests.js @@ -0,0 +1,37 @@ + +function initDatatable(){ + if (window.RequestsDataTables.length === 0 && $('.requests-data-table').length !== 0) { + $('.requests-data-table').each((_, element) => { + + var table = $(element).DataTable( { + "order": [[ 0, "desc" ]], + "paging": true, + "ordering": true, + "searching": true, + "info": true, + "lengthChange": false, + "language": { + "emptyTable": "Currently there are no requests available. -- Start with filling one." + } + }); + + window.RequestsDataTables.push(table); + + // Add event listener for opening and closing details + $('#table_id tbody').on('click', 'td', function () { + var tr = $(this).closest('tr'); + var row = table.row( tr ); + Turbolinks.visit("/glsa/" + row.data()[0]); + } ); + + }); + } +} + +function destroyDatatable() { + while (window.RequestsDataTables.length !== 0) { + window.RequestsDataTables.pop().destroy(); + } +} + +export default {initDatatable, destroyDatatable} diff --git a/web/packs/src/stylesheets/application.scss b/web/packs/src/stylesheets/application.scss new file mode 100644 index 0000000..8d97498 --- /dev/null +++ b/web/packs/src/stylesheets/application.scss @@ -0,0 +1,11 @@ +@import "~@gentoo/tyrian/dist/tyrian"; +@import "~@gentoo/tyrian/dist/components/searchbars"; + +@import "~datatables.net-bs4/css/dataTables.bootstrap4"; +@import "~datatables.net-buttons-bs4/css/buttons.bootstrap4"; + +@import "~taucharts/dist/taucharts"; +@import "~taucharts/dist/plugins/tooltip"; +//@import "~taucharts/dist/taucharts"; + +@import "index"; diff --git a/web/packs/src/stylesheets/index.scss b/web/packs/src/stylesheets/index.scss new file mode 100644 index 0000000..39fa518 --- /dev/null +++ b/web/packs/src/stylesheets/index.scss @@ -0,0 +1,27 @@ +.navigation_link { + color: #777; + font-style: italic; +} + +.comment_tab { + border-top: none; + border-left: none; + border-right: none; + font-size: 13px; + display: table-cell; + padding: 2px 1em; + cursor: pointer; + background: transparent; +} + +.active_comment_tab { + background: transparent; + border-bottom: 4px solid #54487a; + color: #54487a; +} + + +.index_page_icon { + color: #54487A; + text-align: center; +} diff --git a/web/packs/statistics.js b/web/packs/statistics.js new file mode 100644 index 0000000..43f9a27 --- /dev/null +++ b/web/packs/statistics.js @@ -0,0 +1,15 @@ + +Taucharts = require( 'taucharts' ); +require( 'taucharts/dist/plugins/tooltip' ); + + + +var chart = new Taucharts.Chart({ + type: 'horizontal-stacked-bar', + y: 'type', + x: 'count', + color: 'stage', + plugins: [Taucharts.api.plugins.get('tooltip')()], + data: window.CHART_DATA, +}); +chart.renderTo('#bar'); diff --git a/web/packs/stylesheets.js b/web/packs/stylesheets.js new file mode 100644 index 0000000..07a767b --- /dev/null +++ b/web/packs/stylesheets.js @@ -0,0 +1 @@ +import './src/stylesheets/application.scss'; diff --git a/web/templates/about/about.tmpl b/web/templates/about/about.tmpl new file mode 100644 index 0000000..8f22826 --- /dev/null +++ b/web/templates/about/about.tmpl @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html lang="en"> +{{template "head"}} +<body> +{{template "header" .}} + +<div class="container mb-5"> + <div class="row"> + <div class="col-12"> + + + <h1>About GLSAMaker</h1> + + <div class="px-5 py-3"> + + <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> + + <p>Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam varius, turpis et commodo pharetra, est eros bibendum elit, nec luctus magna felis sollicitudin mauris. Integer in mauris eu nibh euismod gravida. Duis ac tellus et risus vulputate vehicula. Donec lobortis risus a elit. Etiam tempor. Ut ullamcorper, ligula eu tempor congue, eros est euismod turpis, id tincidunt sapien risus a quam. Maecenas fermentum consequat mi. Donec fermentum. Pellentesque malesuada nulla a mi. Duis sapien sem, aliquet nec, commodo eget, consequat quis, neque. Aliquam faucibus, elit ut dictum aliquet, felis nisl adipiscing sapien, sed malesuada diam lacus eget erat. Cras mollis scelerisque nunc. Nullam arcu. Aliquam consequat. Curabitur augue lorem, dapibus quis, laoreet et, pretium ac, nisi. Aenean magna nisl, mollis quis, molestie eu, feugiat in, orci. In hac habitasse platea dictumst.</p> + + </div> + + </div> + </div> +</div> + + + +{{template "footer" .}} + +</body> +</html> diff --git a/web/templates/about/aboutCLI.tmpl b/web/templates/about/aboutCLI.tmpl new file mode 100644 index 0000000..beef42a --- /dev/null +++ b/web/templates/about/aboutCLI.tmpl @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html lang="en"> +{{template "head"}} +<body> +{{template "header" .}} + +<div class="container mb-5"> + <div class="row"> + <div class="col-12"> + + <h1>About the Command Line Tool</h1> + + <div class="px-5 py-3"> + + <div class="alert alert-info" role="alert"> + The command line tool is coming soon. + </div> + + </div> + + </div> + </div> +</div> + + + +{{template "footer" .}} + +</body> +</html> diff --git a/web/templates/about/aboutSearch.tmpl b/web/templates/about/aboutSearch.tmpl new file mode 100644 index 0000000..0c6c9f4 --- /dev/null +++ b/web/templates/about/aboutSearch.tmpl @@ -0,0 +1,71 @@ +<!DOCTYPE html> +<html lang="en"> +{{template "head"}} +<body> +{{template "header" .}} + +<div class="container mb-5"> + <div class="row"> + <div class="col-12"> + + + <h1>About the Search</h1> + + <div class="px-5 py-3"> + + The search search can be used to for navigating through the GLSAMaker. The following types of search queries are supported + + <h3 class="mt-4">Navigate to pages</h3> + <ul class="mt-3"> + <li><b>#home</b> will navigate to '/'</li> + <li><b>#dashboard</b> will navigate to '/dashboard'</li> + <li><b>#new</b> will navigate to '/new'</li> + <li><b>#cvetool</b> will navigate to '/cve/tool'</li> + <li><b>#requests</b> will navigate to '/requests'</li> + <li><b>#drafts</b> will navigate to '/drafts'</li> + <li><b>#all</b> will navigate to '/all'</li> + <li><b>#archive</b> will navigate to '/archive'</li> + <li><b>#about</b> will navigate to '/about'</li> + <li><b>#admin</b> will navigate to '/admin'</li> + <li><b>#password</b> will navigate to '/account/password'</li> + <li><b>#2fa</b> will navigate to '/account/2fa'</li> + <li><b>#statistics</b> will navigate to '/statistics'</li> + <li><b>#logout</b> will navigate to '/logout'</li> + <li><b>#bugzilla</b> will navigate to 'https://bugs.gentoo.org'</li> + </ul> + + <h3 class="mt-4">Navigate to GLSAs</h3> + + <ul class="mt-3"> + <li><b>numeric value</b> will navigate to '/glsa/#id'</li> + </ul> + + <h3 class="mt-4">Search for GLSAs</h3> + + <ul class="mt-3"> + <li><b>search string</b> will search for GLSAs in the following fields: + <ul class=""> + <li>title</li> + <li>type</li> + <li>synopsis</li> + <li>description</li> + <li>workaround</li> + <li>resolution</li> + <li>keyword</li> + <li>background</li> + </ul> + </li> + </ul> + + </div> + + </div> + </div> +</div> + + + +{{template "footer" .}} + +</body> +</html> diff --git a/web/templates/account/2fa.tmpl b/web/templates/account/2fa.tmpl new file mode 100644 index 0000000..dcb38a5 --- /dev/null +++ b/web/templates/account/2fa.tmpl @@ -0,0 +1,186 @@ +<!DOCTYPE html> +<html lang="en"> +{{template "head"}} +<body> +{{template "header" .}} + + +<div id="2fa-overview" class="container"> + <div class="row mb-5"> + <div class="col-12"> + <h1>Two Factor Authentication</h1> + </div> + + {{ if .User.Force2FA }} + {{ if .User.IsUsingTOTP }} + {{ else if .User.IsUsingWebAuthn }} + {{ else }} + <div class="col-12 mt-2"> + <div class="alert alert-warning" role="alert"> + Sorry, but you have to enable 2FA for your account before you can continue. + </div> + </div> + {{end}} + {{end}} + + <div class="col-12 px-5 mt-5"> + + <h2>Time-based One-time Passwords{{ if .User.IsUsingTOTP }} <small><span class="ml-2 badge badge-success">active</span></small>{{end}}</h2> + + <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </p> + + </div> + + <div class="col-12 px-5" id="totp-dialog"> + <div class="card mx-auto" style="max-width: 500px;background: none;"> + <div class="card-body"> + + <div class="row"> + <div class="col-6"> + <img src="data:image/png;base64,{{ .QRcode }}" width="100%" /> + </div> + <div class="col-6"> + <p id="token-description" class="mt-4"><small>Please scan the qr-code and enter the six-digit code shown in your Authenticator app.</small></p> + <input id="token" name="token" class="form-control" type="text" style="background: #FAFAFA;" placeholder="123 456"/> + <button id="token-btn" class="btn btn-primary float-right mt-3" onclick="verifyTOTPToken();">Verify</button> + + <style> + + .correct-totp { + border: green solid 1px; + color: green; + } + + .false-totp { + border: red solid 1px; + color: red; + } + + </style> + + <script> + + function verifyTOTPToken(){ + var xhttp = new XMLHttpRequest(); + xhttp.onreadystatechange = function() { + if (this.readyState == 4 && this.status == 200) { + if(this.responseText == "true"){ + document.getElementById("token").classList.remove("false-totp"); + document.getElementById("token").classList.add("correct-totp"); + document.getElementById("token-description").classList.add("text-success"); + document.getElementById("token-description").classList.remove("text-danger"); + }else{ + document.getElementById("token").classList.remove("correct-totp"); + document.getElementById("token").classList.add("false-totp"); + document.getElementById("token-description").classList.remove("text-success"); + document.getElementById("token-description").classList.add("text-danger"); + } + } + }; + xhttp.open("POST", "/account/2fa/totp/verify", true); + xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + xhttp.send("token=" + document.getElementById("token").value); + } + </script> + + </div> + </div> + + </div> + </div> + + </div> + + {{ if .User.IsUsingTOTP }} + <div class="col-12 px-5 text-right"> + <a class="btn btn-outline-danger" href="/account/2fa/totp/disable">Disable</a> + </div> + {{ else }} + <div class="col-12 px-5 text-right"> + <a class="btn btn-outline-success" href="/account/2fa/totp/activate">Activate</a> + </div> + {{ end }} + + <div class="col-12 px-5 py-3"><hr/></div> + + + + <div class="col-12 px-5"> + + <h2>WebAuthn{{ if .User.IsUsingWebAuthn }} <small><span class="ml-2 badge badge-success">active</span></small>{{end}}</h2> + <!-- div: not set up yet --> + <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </p> + + </div> + + + <div class="col-12 px-5" id="totp-dialog"> + <div class="card mx-auto" style="max-width: 500px;background: none;"> + <div class="card-body" style="min-height: 220px;"> + + <div class="row"> + + {{ if .User.WebauthnCredentials }} + <div class="col-6"> + <div class="list-group list-group-flush" style="background: none;"> + {{range .User.WebauthnCredentials}} + <a class="list-group-item list-group-item-action flex-column align-items-start" style="background: none;"> + <h4 class="mb-1"><i class="fa fa-shield" aria-hidden="true"></i> {{CredentialName $.User .}}</h4> + <small class="text-muted">ID: {{ WebAuthnID . }}</small> + </a> + {{end}} + </div> + </div> + {{ else }} + <div class="col-6 text-center"> + <i class="fa fa-exclamation-circle mt-4" aria-hidden="true" style="font-size: 120px;"></i> + <h3>No Authenticators present.</h3> + </div> + {{ end }} + + <div class="col-6"> + <p id="token-description" class="mt-2"><small>Click on the button below to add a new authenticator.</small></p> + <input id="webauthn-name" name="token" class="form-control" maxlength="20" type="text" style="background: #FAFAFA;" placeholder="Authenticator Name"/> + + <button id="register-webauthn" class="btn btn-primary float-right mt-4">Add New</button> + {{ if .User.WebauthnCredentials }} + <button class="btn btn-outline-danger float-right mt-4 mr-2">Delete All</button> + {{ end }} + + + </div> + </div> + + </div> + </div> + + </div> + + + {{ if .User.IsUsingWebAuthn }} + <div class="col-12 px-5 mt-3 text-right"> + <a class="btn btn-outline-danger" href="/account/2fa/webauthn/disable">Disable</a> + </div> + {{ else }} + <div class="col-12 px-5 mt-3 text-right"> + <a class="btn btn-outline-success" href="/account/2fa/webauthn/activate">Activate</a> + </div> + {{ end }} + + </div> + + + + + + +</div> + + +{{template "footer" .}} + +<script src="/assets/account.js"></script> + + +</body> +</html> diff --git a/web/templates/account/password/forcedchange.tmpl b/web/templates/account/password/forcedchange.tmpl new file mode 100644 index 0000000..d80b874 --- /dev/null +++ b/web/templates/account/password/forcedchange.tmpl @@ -0,0 +1,98 @@ +{{define "forcedPasswordChange"}} + + <!DOCTYPE html> + <html lang="en"> + + <head> + <title>Gentoo Security</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <meta name="theme-color" content="#54487a"> + <meta name="description" content="Gentoo CVE Tool"> + + <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> + + <link rel="icon" href="https://packages.gentoo.org/favicon.ico" type="image/x-icon"> + </head> + + <body style="border-top: none;background: #fff;"> + + <div class="container vh-100 d-flex"> + <div class="row flex-grow-1"> + <div class="col-12 d-flex align-items-center"> + + <div class="row w-100"> + + <div class="col-12 align-items-center"> + <div class="card border-grey mx-auto" style="max-width: 430px;border-color: lightgrey!important;"> + <div class="card-body"> + <div class="text-center" style="margin-top:10px;margin-bottom:20px;"> + <object data="https://www.gentoo.org/assets/img/logo/gentoo-signet.svg" type="image/svg+xml" style="max-width: 80px;"> + <img src="https://assets.gentoo.org/tyrian/site-logo.png" alt="Gentoo Linux logo"> + </object> + <h4 class="mt-2">Change your Password</h4> + </div> + + <div class="text-left" style="padding-left: 1.25rem;padding-right: 1.25rem;"> + Sorry, but you have to change your password, before you can continue. + </div> + + <form action="/account/password" method="POST"> + <div class="card mx-auto" style="max-width: 600px;background: none;border: none;"> + <div class="card-body"> + <input name="oldPassword" class="my-2" type="password" style="width: 100%;" placeholder="Old Password"/> + <input name="newPassword" class="my-2" type="password" style="width: 100%;" placeholder="New Password"/> + <input name="confirmedNewPassword" class="my-2" type="password" style="width: 100%;" placeholder="Confirm New Password"/> + <button type="submit" class="mt-2 float-right btn btn-primary" style="border-color: #54487A!important;background-color: #54487A!important;"> Change </button> + </div> + </div> + </form> + + </div> + </div> + </div> + + <div class="col-12 mt-3 align-items-center"> + <div class="card border-0 text-right text-muted mx-auto" style="max-width: 430px;"> + <span class="" style="font-size: 80%;"> + <a class="mr-4 text-muted" style="text-decoration: none;" data-toggle="collapse" href="#create-new-account-notice" role="button" aria-expanded="false" aria-controls="multiCollapseExample1">New Account</a> + <a class="text-muted" style="text-decoration: none;" data-toggle="collapse" href="#reset-password-notice" role="button" aria-expanded="false" aria-controls="multiCollapseExample1">Reset Password</a> + </span> + + + + <div class="card-body"> + <div class="collapse mt-2" id="create-new-account-notice"> + <div class="card card-body border-0 p-0"> + <small>To create a new account, please contact the security team and request access.</small> + </div> + </div> + + <div class="collapse mt-2" id="reset-password-notice"> + <div class="card card-body border-0 p-0"> + <small>In case you've forgotten your password, please contact the security team and ask an admin to reset your password.</small> + </div> + </div> + </div> + + </div> + </div> + + </div> + </div> + + + + </div> + </div> + + + <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script> + <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> + + + </body> + </html> + +{{end}} diff --git a/web/templates/account/password/normalchange.tmpl b/web/templates/account/password/normalchange.tmpl new file mode 100644 index 0000000..48b35bd --- /dev/null +++ b/web/templates/account/password/normalchange.tmpl @@ -0,0 +1,45 @@ +{{define "normalPasswordChange"}} + + <!DOCTYPE html> + <html lang="en"> + {{template "head"}} + <body> + {{template "header" .}} + + + <div id="2fa-overview" class="container"> + <div class="row mb-5"> + <div class="col-12"> + <h1>Change your password</h1> + </div> + + {{if .Message}} + <div class="col-12"> + <div class="alert alert-{{if .Success}}success{{else}}danger{{end}}" role="alert"> + {{.Message}} + </div> + </div> + {{end}} + + <div class="col-12 mt-4 px-5" id="totp-dialog"> + <form action="/account/password" method="POST"> + <div class="card mx-auto" style="max-width: 600px;background: none;border: none;"> + <div class="card-body"> + <input name="oldPassword" class="my-2" type="password" style="width: 100%;" placeholder="Old Password"/> + <input name="newPassword" class="my-2" type="password" style="width: 100%;" placeholder="New Password"/> + <input name="confirmedNewPassword" class="my-2" type="password" style="width: 100%;" placeholder="Confirm New Password"/> + <button type="submit" class="mt-2 float-right btn btn-primary"> Change </button> + </div> + </div> + </form> + </div> + </div> + </div> + + + {{template "footer" .}} + + </body> + </html> + +{{end}} diff --git a/web/templates/account/password/password.tmpl b/web/templates/account/password/password.tmpl new file mode 100644 index 0000000..5f996c9 --- /dev/null +++ b/web/templates/account/password/password.tmpl @@ -0,0 +1,5 @@ +{{if .User.ForcePasswordRotation}} + {{template "forcedPasswordChange" .}} +{{else}} + {{template "normalPasswordChange" .}} +{{end}} diff --git a/web/templates/admin/components/global.tmpl b/web/templates/admin/components/global.tmpl new file mode 100644 index 0000000..c0a5fe0 --- /dev/null +++ b/web/templates/admin/components/global.tmpl @@ -0,0 +1,45 @@ +{{define "viewGlobal"}} + <div class="col-12 mt-4"> + <div class="card"> + <div class="card-header" style="padding-left: 8px; padding-right: 8px; padding-top: 4px; padding-bottom: 4px;font-weight:bold;font-size:13px;"> + <i class="fa fa-caret-right" aria-hidden="true" style="margin-right:5px;cursor: pointer"></i> Global 2FA Settings (coming soon) + <i class="fa fa-pencil float-right mt-1 text-muted d-none" aria-hidden="true" style="margin-right:5px;"></i> + </div> + <div class="card-body d-none"> + <div class="row"> + <div class="col-sm-6 text-muted"> + Force 2FA to login (coming soon) + <i class="fa fa-times float-right mr-3 p-1" style="color: darkred;" aria-hidden="true"></i> + </div> + <div class="col-sm-6 text-muted"> + Force 2FA to release GLSA (coming soon) + <i class="fa fa-times float-right mr-3 p-1" style="color: darkred;" aria-hidden="true"></i> + </div> + </div> + </div> + </div> + </div> +{{end}} + +{{define "editGlobal"}} + <div class="col-12 mt-4"> + <div class="card"> + <div class="card-header" style="padding-left: 8px; padding-right: 8px; padding-top: 4px; padding-bottom: 4px;font-weight:bold;font-size:13px;"> + <i class="fa fa-caret-down" aria-hidden="true" style="margin-right:5px;cursor: pointer"></i> Global 2FA Settings + <i class="fa fa-pencil float-right mt-1" aria-hidden="true" style="margin-right:5px;cursor: pointer"></i> + </div> + <div class="card-body"> + <div class="row"> + <div class="col-sm-6"> + Force 2FA to login + <i class="fa fa-times float-right mr-3 p-1" style="color: darkred;" aria-hidden="true"></i> + </div> + <div class="col-sm-6 text-muted"> + Force 2FA to release GLSA (coming soon) + <i class="fa fa-times float-right mr-3 p-1" style="color: darkred;" aria-hidden="true"></i> + </div> + </div> + </div> + </div> + </div> +{{end}} diff --git a/web/templates/admin/components/permissions.tmpl b/web/templates/admin/components/permissions.tmpl new file mode 100644 index 0000000..32b7dc6 --- /dev/null +++ b/web/templates/admin/components/permissions.tmpl @@ -0,0 +1,424 @@ +{{define "viewPermissions"}} + <div class="col-12 mt-4"> + <div class="card"> + <div class="card-header" style="padding-left: 8px; padding-right: 8px; padding-top: 4px; padding-bottom: 4px;font-weight:bold;font-size:13px;"> + <a onclick="this.getElementsByTagName('i')[0].classList.toggle('fa-caret-down');this.getElementsByTagName('i')[0].classList.toggle('fa-caret-right');" style="outline : none;text-decoration: none;color:#000;" data-toggle="collapse" href="#collapsePermissionSettings"><i class="fa fa-caret-down" aria-hidden="true" style="margin-right:5px;cursor: pointer"></i> User Permissions</a> + <a href="/admin/edit/permissions"><i class="fa fa-pencil float-right mt-1" aria-hidden="true" style="margin-right:5px;cursor: pointer;color:black;"></i></a> + </div> + <div class="card-body collapse show" id="collapsePermissionSettings"> + <table class="table table-striped"> + <thead> + <tr> + <td style="border-top:none;"></td> + <th colspan="11" class="border-0">GLSA</th> + <th colspan="6" class="border-0">CVE</th> + <th colspan="4" class="border-0">Admin</th> + </tr> + <tr> + <th>User</th> + <!-- GLSA Permissions --> + <th title="View GLSAs"> + <i class="fa fa-eye" aria-hidden="true"></i> + </th> + <th title="Manually trigger an update of the Bug data"> + <i class="fa fa-refresh" aria-hidden="true"></i> + </th> + <th title="Add comments to GLSAs"> + <i class="fa fa-commenting-o" aria-hidden="true"></i> + </th> + <th title="Add GLSAs"> + <i class="fa fa-plus" aria-hidden="true"></i> + </th> + <th title="Edit GLSAs"> + <i class="fa fa-pencil" aria-hidden="true"></i> + </th> + <th title="Delete GLSAs"> + <i class="fa fa-trash-o" aria-hidden="true"></i> + </th> + <th title="Approve GLSAs"> + <i class="fa fa-thumbs-o-up" aria-hidden="true"></i> + </th> + <th title="Approve own GLSAs"> + <i class="fa fa-thumbs-up" aria-hidden="true"></i> + </th> + <th title="Decline GLSAs"> + <i class="fa fa-thumbs-o-down" aria-hidden="true"></i> + </th> + <th title="Release GLSAs"> + <i class="fa fa-paper-plane-o" aria-hidden="true"></i> + </th> + <th title="View confidential GLSAs"> + <i class="fa fa-user-secret" aria-hidden="true"></i> + </th> + <!-- CVE Permissions --> + <th title="View the CVETool"> + <i class="fa fa-eye" aria-hidden="true"></i> + </th> + <th title="Manually trigger an update of the CVE data"> + <i class="fa fa-refresh" aria-hidden="true"></i> + </th> + <th title="Add comments to CVEs"> + <i class="fa fa-commenting-o" aria-hidden="true"></i> + </th> + <th title="Add packages to CVEs"> + <i class="fa fa-hdd-o" aria-hidden="true"></i> + </th> + <th title="Change the State of CVEs"> + <i class="fa fa-random" aria-hidden="true"></i> + </th> + <th title="Assign and Create Bugs using the CVETool"> + <i class="fa fa-bug" aria-hidden="true"></i> + </th> + <!-- Admin Permissions --> + <th title="View Admin Area"> + <i class="fa fa-eye" aria-hidden="true"></i> + </th> + <th title="Manage Templates"> + <i class="fa fa-files-o" aria-hidden="true"></i> + </th> + <th title="Manage Global Settings"> + <i class="fa fa-globe" aria-hidden="true"></i> + </th> + <th title="Manage Users"> + <i class="fa fa-users" aria-hidden="true"></i> + </th> + </tr> + </thead> + <tbody> + {{range .Users}} + <tr> + <td>{{.Email}}</td> + <!-- GLSA Permissions --> + <td> + {{if .Permissions.Glsa.View}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if .Permissions.Glsa.UpdateBugs}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if .Permissions.Glsa.Comment}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if .Permissions.Glsa.Create}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if .Permissions.Glsa.Edit}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if .Permissions.Glsa.Delete}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if .Permissions.Glsa.Approve}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if .Permissions.Glsa.ApproveOwnGlsa}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if .Permissions.Glsa.Decline}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if .Permissions.Glsa.Release}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if .Permissions.Glsa.Confidential}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <!-- CVE Permissions --> + <td> + {{if .Permissions.CVETool.View}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if .Permissions.CVETool.UpdateCVEs}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if .Permissions.CVETool.Comment}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if .Permissions.CVETool.AddPackage}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if .Permissions.CVETool.ChangeState}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if .Permissions.CVETool.AssignBug}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <!-- Admin Permissions --> + <td> + {{if .Permissions.Admin.View}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if .Permissions.Admin.CreateTemplates}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if .Permissions.Admin.GlobalSettings}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if .Permissions.Admin.ManageUsers}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + </tr> + {{end}} + + </tbody> + </table> + </div> + </div> + </div> +{{end}} + + + +{{define "editPermissions"}} + <div class="col-12 mt-4"> + <form action="/admin/edit/permissions" method="post"> + <input value="1" name="edit" hidden /> + <div class="card"> + <div class="card-header" style="padding-left: 8px; padding-right: 8px; padding-top: 4px; padding-bottom: 4px;font-weight:bold;font-size:13px;"> + <i class="fa fa-caret-down" aria-hidden="true" style="margin-right:5px;cursor: pointer"></i> User Permissions + <button type="submit" class="btn btn-sm p-0 float-right"><i class="fa fa-save float-right mt-1" aria-hidden="true" style="margin-right:5px;cursor: pointer;color:black;"></i></button> + </div> + <div class="card-body"> + <table class="table"> + <thead> + <tr> + <td style="border-top:none;"></td> + <th colspan="11" class="border-0">GLSA</th> + <th colspan="6" class="border-0">CVE</th> + <th colspan="4" class="border-0">Admin</th> + </tr> + <tr> + <th>User</th> + <!-- GLSA Permissions --> + <th title="View GLSAs"> + <i class="fa fa-eye" aria-hidden="true"></i> + </th> + <th title="Manually trigger an update of the Bug data"> + <i class="fa fa-refresh" aria-hidden="true"></i> + </th> + <th title="Add comments to GLSAs"> + <i class="fa fa-commenting-o" aria-hidden="true"></i> + </th> + <th title="Add GLSAs"> + <i class="fa fa-plus" aria-hidden="true"></i> + </th> + <th title="Edit GLSAs"> + <i class="fa fa-pencil" aria-hidden="true"></i> + </th> + <th title="Delete GLSAs"> + <i class="fa fa-trash-o" aria-hidden="true"></i> + </th> + <th title="Approve GLSAs"> + <i class="fa fa-thumbs-o-up" aria-hidden="true"></i> + </th> + <th title="Approve own GLSAs"> + <i class="fa fa-thumbs-up" aria-hidden="true"></i> + </th> + <th title="Decline GLSAs"> + <i class="fa fa-thumbs-o-down" aria-hidden="true"></i> + </th> + <th title="Release GLSAs"> + <i class="fa fa-paper-plane-o" aria-hidden="true"></i> + </th> + <th title="View confidential GLSAs"> + <i class="fa fa-user-secret" aria-hidden="true"></i> + </th> + <!-- CVE Permissions --> + <th title="View the CVETool"> + <i class="fa fa-eye" aria-hidden="true"></i> + </th> + <th title="Manually trigger an update of the CVE data"> + <i class="fa fa-refresh" aria-hidden="true"></i> + </th> + <th title="Add comments to CVEs"> + <i class="fa fa-commenting-o" aria-hidden="true"></i> + </th> + <th title="Add packages to CVEs"> + <i class="fa fa-hdd-o" aria-hidden="true"></i> + </th> + <th title="Change the State of CVEs"> + <i class="fa fa-random" aria-hidden="true"></i> + </th> + <th title="Assign and Create Bugs using the CVETool"> + <i class="fa fa-bug" aria-hidden="true"></i> + </th> + <!-- Admin Permissions --> + <th title="View Admin Area"> + <i class="fa fa-eye" aria-hidden="true"></i> + </th> + <th title="Manage Templates"> + <i class="fa fa-files-o" aria-hidden="true"></i> + </th> + <th title="Manage Global Settings"> + <i class="fa fa-globe" aria-hidden="true"></i> + </th> + <th title="Manage Users"> + <i class="fa fa-users" aria-hidden="true"></i> + </th> + </tr> + </thead> + <tbody> + {{range .Users}} + <tr> + <td> + <input name="user" type="text" value="{{.Id}}" hidden/> + {{.Email}} + </td> + <!-- GLSA Permissions --> + <td> + <input name="glsa-view" type="checkbox" value="{{.Id}}" {{if .Permissions.Glsa.View}}checked{{end}}/> + </td> + <td> + <input name="glsa-updateBugs" type="checkbox" value="{{.Id}}" {{if .Permissions.Glsa.UpdateBugs}}checked{{end}}/> + </td> + <td> + <input name="glsa-comment" type="checkbox" value="{{.Id}}" {{if .Permissions.Glsa.Comment}}checked{{end}}/> + </td> + <td> + <input name="glsa-create" type="checkbox" value="{{.Id}}" {{if .Permissions.Glsa.Create}}checked{{end}}/> + </td> + <td> + <input name="glsa-edit" type="checkbox" value="{{.Id}}" {{if .Permissions.Glsa.Edit}}checked{{end}}/> + </td> + <td> + <input name="glsa-delete" type="checkbox" value="{{.Id}}" {{if .Permissions.Glsa.Delete}}checked{{end}}/> + </td> + <td> + <input name="glsa-approve" type="checkbox" value="{{.Id}}" {{if .Permissions.Glsa.Approve}}checked{{end}}/> + </td> + <td> + <input name="glsa-approveOwnGlsa" type="checkbox" value="{{.Id}}" {{if .Permissions.Glsa.ApproveOwnGlsa}}checked{{end}}/> + </td> + <td> + <input name="glsa-decline" type="checkbox" value="{{.Id}}" {{if .Permissions.Glsa.Decline}}checked{{end}}/> + </td> + <td> + <input name="glsa-release" type="checkbox" value="{{.Id}}" {{if .Permissions.Glsa.Release}}checked{{end}}/> + </td> + <td> + <input name="glsa-confidential" type="checkbox" value="{{.Id}}" {{if .Permissions.Glsa.Confidential}}checked{{end}}/> + </td> + <!-- CVE Permissions --> + <td> + <input name="cve-view" type="checkbox" value="{{.Id}}" {{if .Permissions.CVETool.View}}checked{{end}}/> + </td> + <td> + <input name="cve-updateCVEs" type="checkbox" value="{{.Id}}" {{if .Permissions.CVETool.UpdateCVEs}}checked{{end}}/> + </td> + <td> + <input name="cve-comment" type="checkbox" value="{{.Id}}" {{if .Permissions.CVETool.Comment}}checked{{end}}/> + </td> + <td> + <input name="cve-addPackage" type="checkbox" value="{{.Id}}" {{if .Permissions.CVETool.AddPackage}}checked{{end}}/> + </td> + <td> + <input name="cve-changeState" type="checkbox" value="{{.Id}}" {{if .Permissions.CVETool.ChangeState}}checked{{end}}/> + </td> + <td> + <input name="cve-assignBug" type="checkbox" value="{{.Id}}" {{if .Permissions.CVETool.AssignBug}}checked{{end}}/> + </td> + <!-- Admin Permissions --> + <td> + <input name="admin-view" type="checkbox" value="{{.Id}}" {{if .Permissions.Admin.View}}checked{{end}}/> + </td> + <td> + <input name="admin-createTemplates" type="checkbox" value="{{.Id}}" {{if .Permissions.Admin.CreateTemplates}}checked{{end}}/> + </td> + <td> + <input name="admin-globalSettings" type="checkbox" value="{{.Id}}" {{if .Permissions.Admin.GlobalSettings}}checked{{end}}/> + </td> + <td> + <input name="admin-manageUsers" type="checkbox" value="{{.Id}}" {{if .Permissions.Admin.ManageUsers}}checked{{end}}/> + </td> + </tr> + {{end}} + + </tbody> + </table> + </div> + </div> + </form> + </div> +{{end}} + diff --git a/web/templates/admin/components/templates.tmpl b/web/templates/admin/components/templates.tmpl new file mode 100644 index 0000000..470b229 --- /dev/null +++ b/web/templates/admin/components/templates.tmpl @@ -0,0 +1,10 @@ +{{define "viewTemplates"}} + <div class="col-12 mt-4"> + <div class="card"> + <div class="card-header" style="padding-left: 8px; padding-right: 8px; padding-top: 4px; padding-bottom: 4px;font-weight:bold;font-size:13px;"> + <i class="fa fa-caret-right" aria-hidden="true" style="margin-right:5px;cursor: pointer"></i> Template Management (coming soon) + <i class="fa fa-pencil float-right mt-1 text-muted d-none" aria-hidden="true" style="margin-right:5px;"></i> + </div> + </div> + </div> +{{end}} diff --git a/web/templates/admin/components/users.tmpl b/web/templates/admin/components/users.tmpl new file mode 100644 index 0000000..b7b2e87 --- /dev/null +++ b/web/templates/admin/components/users.tmpl @@ -0,0 +1,226 @@ + +{{define "viewUsers"}} + + <div class="col-12 mt-4"> + <div class="card"> + <div class="card-header" style="padding-left: 8px; padding-right: 8px; padding-top: 4px; padding-bottom: 4px;font-weight:bold;font-size:13px;"> + <a onclick="this.getElementsByTagName('i')[0].classList.toggle('fa-caret-down');this.getElementsByTagName('i')[0].classList.toggle('fa-caret-right');" style="outline : none;text-decoration: none;color:#000;" data-toggle="collapse" href="#collapseUserSettings"><i class="fa fa-caret-down" aria-hidden="true" style="margin-right:5px;cursor: pointer"></i> User Management</a> + <a href="/admin/edit/users"><i class="fa fa-pencil float-right mt-1" aria-hidden="true" style="margin-right:5px;cursor: pointer;color:black;"></i></a> + </div> + <div class="card-body collapse show" id="collapseUserSettings"> + <table class="table"> + <thead> + <tr> + <th class="border-0" title="Badge of the user">Badge</th> + <th class="border-0" title="Nickname of the user">Nick</th> + <th class="border-0" title="Full name of the user">Name</th> + <th class="border-0" title="E-Mail address of the user">Email</th> + <th class="border-0" title="Does the user use TOTP?">TOTP</th> + <th class="border-0" title="Does the user use WebAuthn?">WebAuthn</th> + <th class="border-0" title="User is forced to rotate the password at the next login">Rotate Password</th> + <th class="border-0" title="User is forced to use either TOTP or WebAuthn">Force 2FA</th> + <th class="border-0" title="Is the user-account active? If disabled ">Active</th> + </tr> + </thead> + <tbody> + {{range .Users}} + <tr> + <td> + + <span class="badge badge-secondary float-left mr-2" style="background: none;border: 1px solid {{.Badge.Color}};"> + <i class="fa fa-user mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{.Badge.Color}};"></i> + <span class="text-uppercase" style="color:{{.Badge.Color}};">{{.Badge.Name}}</span> + </span> + + </td> + <td>{{.Nick}}</td> + <td>{{.Name}}</td> + <td>{{.Email}}</td> + <td> + {{if .IsUsingTOTP}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if .IsUsingWebAuthn}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if .ForcePasswordRotation}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if .Force2FA}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if not .Disabled}} + <i class="fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + </tr> + {{end}} + </tbody> + </table> + + {{if .NewUserNick}} + <div class="alert alert-success" role="alert"> + The User <i>{{.NewUserNick}}</i> has been successfully created. The temporary password <i>{{.NewUserPassword}}</i> has been generated for this account. The user has to change the password during the next login. + </div> + {{end}} + + </div> + </div> + </div> + +{{end}} + + + +{{define "editUsers"}} + + <div class="col-12 mt-4"> + <form action="/admin/edit/users" method="post"> + <input value="1" name="edit" hidden /> + <div class="card"> + <div class="card-header" style="padding-left: 8px; padding-right: 8px; padding-top: 4px; padding-bottom: 4px;font-weight:bold;font-size:13px;"> + <i class="fa fa-caret-down" aria-hidden="true" style="margin-right:5px;cursor: pointer"></i> User Management + <a href="/admin"><i class="fa fa-times float-right mt-1" aria-hidden="true" style="margin-right:5px;cursor: pointer;color:black;"></i></a> + <button type="submit" class="btn btn-sm mr-1 p-0 float-right"><i class="fa fa-save float-right mt-1" aria-hidden="true" style="margin-right:5px;cursor: pointer;color:black;"></i></button> + </div> + <div class="card-body"> + <table class="table"> + <thead> + <tr> + <th class="border-0" title="Badge of the user">Badge</th> + <th class="border-0" title="Nickname of the user">Nick</th> + <th class="border-0" title="Full name of the user">Name</th> + <th class="border-0" title="E-Mail address of the user">Email</th> + <th class="border-0" title="Does the user use TOTP?">TOTP</th> + <th class="border-0" title="Does the user use WebAuthn?">WebAuthn</th> + <th class="border-0" title="User is forced to rotate the password at the next login">Rotate Password</th> + <th class="border-0" title="User is forced to use either TOTP or WebAuthn">Force 2FA</th> + <th class="border-0" title="Is the user-account active? If disabled ">Active</th> + <th class="border-0"></th> + </tr> + </thead> + <tbody id="userList"> + {{range .Users}} + <tr> + <td> + <span class="my-1 badge badge-secondary float-left mr-2" style="background: none;border: 1px solid {{.Badge.Color}};"> + <i class="fa fa-user mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{.Badge.Color}};"></i> + <span class="text-uppercase" style="color:{{.Badge.Color}};">{{.Badge.Name}}</span> + </span> + </td> + <td> + <input name="userId" type="text" value="{{.Id}}" hidden/> + <input name="userNick" class="form-control form-control-sm" value="{{.Nick}}" style="max-width: 150px;"/> + </td> + <td> + <input name="userName" class="form-control form-control-sm" value="{{.Name}}" style="max-width: 150px;"/> + </td> + <td> + <input name="userEmail" class="form-control form-control-sm" value="{{.Email}}" style="max-width: 150px;"/> + </td> + <td> + {{if .IsUsingTOTP}} + <i class="my-2 fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="my-2 fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + {{if .IsUsingWebAuthn}} + <i class="my-2 fa fa-check" style="color: green;" aria-hidden="true"></i> + {{else}} + <i class="my-2 fa fa-times" style="color: darkred;" aria-hidden="true"></i> + {{end}} + </td> + <td> + <input name="userPasswordRotation" class="m-2" type="checkbox" value="{{.Id}}" {{if .ForcePasswordRotation}}checked{{end}}/> + </td> + <td> + <input name="userForce2FA" class="m-2" type="checkbox" value="{{.Id}}" {{if .Force2FA}}checked{{end}}/> + </td> + <td> + <input name="userActive" class="m-2" type="checkbox" value="{{.Id}}" {{if not .Disabled}}checked{{end}}/> + </td> + <td> + + + <div class="dropdown"> + + <button type="button" class="float-right my-1 py-0 btn btn-outline-secondary btn-sm dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Actions</button> + + <div class="dropdown-menu" aria-labelledby="dropdownMenuButton"> + <a class="dropdown-item" href="/admin/edit/password/reset/{{.Id}}">Reset Password</a> + </div> + </div> + + + </td> + </tr> + {{end}} + + </tbody> + + <tbody id="addUserForm" class="border-0 pt-2"> + <tr> + <td> + <span class="badge badge-secondary float-left mr-2" style="background: none;border: 1px solid grey;"> + <i class="fa fa-user mr-1" aria-hidden="true" style="font-size: 0.8rem;color: grey;"></i> + <span class="text-uppercase" style="color:grey;">user</span> + </span> + </td> + <td> + <input id="newNick" class="form-control form-control-sm" placeholder="nickname" value="" style="max-width: 150px;"/> + </td> + <td> + <input id="newName" class="form-control form-control-sm" placeholder="full name" value="" style="max-width: 150px;"/> + </td> + <td> + <input id="newEmail" class="form-control form-control-sm" placeholder="email" value="" style="max-width: 150px;"/> + </td> + <td> + <i class="my-2 fa fa-times" style="color: darkred;" aria-hidden="true"></i> + </td> + <td> + <i class="my-2 fa fa-times" style="color: darkred;" aria-hidden="true"></i> + </td> + <td> + <input class="m-2" type="checkbox" checked disabled/> + </td> + <td> + <input class="m-2" type="checkbox"/> + </td> + <td> + <input class="m-2" type="checkbox" /> + </td> + <td> + <button id="addUser" type="button" class="float-right my-1 py-0 btn btn-outline-success btn-sm">Add</button> + </td> + </tr> + </tbody> + + </table> + </div> + </div> + </form> + </div> + +{{end}} + diff --git a/web/templates/admin/edit/permissions.tmpl b/web/templates/admin/edit/permissions.tmpl new file mode 100644 index 0000000..c25d2ea --- /dev/null +++ b/web/templates/admin/edit/permissions.tmpl @@ -0,0 +1,36 @@ +<!DOCTYPE html> +<html lang="en"> +{{template "head"}} +<body> +{{template "header" .}} + +<div class="container mb-5"> + <div class="row"> + <div class="col-12"> + + + <h1>Admin Area</h1> + + <div class="row"> + + {{template "viewGlobal"}} + + {{template "viewUsers" .}} + + {{template "editPermissions" .}} + + {{template "viewTemplates"}} + + </div> + + </div> + </div> +</div> + + + +{{template "footer" .}} + + +</body> +</html> diff --git a/web/templates/admin/edit/users.tmpl b/web/templates/admin/edit/users.tmpl new file mode 100644 index 0000000..68b1b8e --- /dev/null +++ b/web/templates/admin/edit/users.tmpl @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<html lang="en"> +{{template "head"}} +<body> +{{template "header" .}} + +<div class="container mb-5"> + <div class="row"> + <div class="col-12"> + + + <h1>Admin Area</h1> + + <div class="row"> + + {{template "viewGlobal"}} + + {{template "editUsers" .}} + + {{template "viewPermissions" .}} + + {{template "viewTemplates"}} + + </div> + + </div> + </div> +</div> + + + +{{template "footer" .}} + +<script src="/assets/admin.js"></script> + +</body> +</html> diff --git a/web/templates/admin/passwordreset.tmpl b/web/templates/admin/passwordreset.tmpl new file mode 100644 index 0000000..9b386f0 --- /dev/null +++ b/web/templates/admin/passwordreset.tmpl @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<html lang="en"> +{{template "head"}} +<body> +{{template "header" .}} + +<div class="container mb-5"> + <div class="row"> + <div class="col-12"> + + + <h1>Reset Password of {{.UserNick}}?</h1> + + <div class="row"> + + <div class="mx-auto"> + <form action="/admin/edit/password/reset/{{.UserId}}" method="POST"> + <a href="/admin" class="btn btn-outline-danger">No</a> + <button type="submit" class="btn btn-success">Yes</button> + </form> + </div> + + </div> + + </div> + </div> +</div> + + + +{{template "footer" .}} + + +</body> +</html> diff --git a/web/templates/admin/view.tmpl b/web/templates/admin/view.tmpl new file mode 100644 index 0000000..2b32fdc --- /dev/null +++ b/web/templates/admin/view.tmpl @@ -0,0 +1,41 @@ +<!DOCTYPE html> +<html lang="en"> +{{template "head"}} +<body> +{{template "header" .}} + +<div class="container mb-5"> + <div class="row"> + <div class="col-12"> + + + <h1>Admin Area</h1> + + <div class="row"> + + {{if .User.Permissions.Admin.GlobalSettings}} + {{template "viewGlobal"}} + {{end}} + + {{if .User.Permissions.Admin.ManageUsers}} + {{template "viewUsers" .}} + {{template "viewPermissions" .}} + {{end}} + + {{if .User.Permissions.Admin.CreateTemplates}} + {{template "viewTemplates"}} + {{end}} + + </div> + + </div> + </div> +</div> + + + +{{template "footer" .}} + + +</body> +</html> diff --git a/web/templates/all/all.tmpl b/web/templates/all/all.tmpl new file mode 100644 index 0000000..1280ea4 --- /dev/null +++ b/web/templates/all/all.tmpl @@ -0,0 +1,86 @@ +<!DOCTYPE html> +<html lang="en"> +{{template "head"}} +<body> +{{template "header" .}} + +<style> + td:hover { + cursor: pointer; + } +</style> + +<div class="container mb-5"> + <div class="row"> + <div class="col-12"> + + + <h1>All</h1> + + <table id="table_id" class="all-data-table table table-hover"> + <thead> + <tr> + <th>ID</th> + <th>Type</th> + <th>Title</th> + <th>Requester</th> + <th>Date</th> + <th>Bug Ready</th> + <th>Approved</th> + <th>Workflow</th> + <th>Permissions</th> + </tr> + </thead> + <tbody> + + {{ range .All}} + <tr> + <td>{{.Id}}</td> + <td><span class="badge {{if eq .Type "request"}}badge-danger{{else if eq .Type "draft"}}badge-warning{{else}}badge-success{{end}} text-capitalize">{{.Type}}</span></td> + <td>{{.Title}}</td> + <td>{{.Creator.Nick}}</td> + <td>{{.Created}}</td> + <td> + <span class="badge badge-secondary float-right mr-2" style="background: none;border: 1px solid {{if .Status.BugReady }}green{{else}}darkred{{end}};padding-top:4px!important;padding-bottom:1.6px;"> + <svg class="" style="width:13px;height:13px" viewBox="0 0 24 24"> + <path fill="{{if .Status.BugReady }}green{{else}}darkred{{end}}" d="M20,8H17.19C16.74,7.2 16.12,6.5 15.37,6L17,4.41L15.59,3L13.42,5.17C12.96,5.06 12.5,5 12,5C11.5,5 11.05,5.06 10.59,5.17L8.41,3L7,4.41L8.62,6C7.87,6.5 7.26,7.21 6.81,8H4V10H6.09C6.03,10.33 6,10.66 6,11V12H4V14H6V15C6,15.34 6.03,15.67 6.09,16H4V18H6.81C8.47,20.87 12.14,21.84 15,20.18C15.91,19.66 16.67,18.9 17.19,18H20V16H17.91C17.97,15.67 18,15.34 18,15V14H20V12H18V11C18,10.66 17.97,10.33 17.91,10H20V8M16,15A4,4 0 0,1 12,19A4,4 0 0,1 8,15V11A4,4 0 0,1 12,7A4,4 0 0,1 16,11V15M14,10V12H10V10H14M10,14H14V16H10V14Z" /> + </svg> + <span class="" style="color:{{if .Status.BugReady }}green{{else}}darkred{{end}};">{{if .Status.BugReady }}READY{{else}}NOT READY{{end}}</span> + </span> + + </td> + <td> + <span class="badge badge-secondary float-right mr-2" style="background: none;border: 1px solid {{if eq .Status.Approval "declined" }}darkred{{else if eq .Status.Approval "approved"}}green{{else if eq .Status.Approval "comments"}}orange{{else}}grey{{end}};"> + <i class="fa fa-circle mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{if eq .Status.Approval "declined" }}darkred{{else if eq .Status.Approval "approved"}}green{{else if eq .Status.Approval "comments"}}orange{{else}}grey{{end}};"></i> + <span class="text-uppercase" style="color:{{if eq .Status.Approval "declined" }}darkred{{else if eq .Status.Approval "approved"}}green{{else if eq .Status.Approval "comments"}}orange{{else}}grey{{end}};">{{.Status.Approval}}</span> + </span> + </td> + <td> + <span class="badge badge-danger float-right mr-2" style="background: none;border: 1px solid {{if eq .Status.WorkflowStatus "commented" }}blue{{else if eq .Status.WorkflowStatus "own"}}green{{else if eq .Status.WorkflowStatus "approved"}}green{{else}}darkred{{end}};"> + <i class="fa {{if eq .Status.WorkflowStatus "commented" }}fa-comments-o{{else if eq .Status.WorkflowStatus "own"}}fa-user{{else if eq .Status.WorkflowStatus "approved"}}fa-check-circle-o{{else}}fa-times-circle{{end}} mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{if eq .Status.WorkflowStatus "commented" }}blue{{else if eq .Status.WorkflowStatus "own"}}green{{else if eq .Status.WorkflowStatus "approved"}}green{{else}}darkred{{end}};"></i> + <span class="text-uppercase" style="color:{{if eq .Status.WorkflowStatus "commented" }}blue{{else if eq .Status.WorkflowStatus "own"}}green{{else if eq .Status.WorkflowStatus "approved"}}green{{else}}darkred{{end}};">{{.Status.WorkflowStatus}}</span> + </span> + </td> + <td> + <span class="badge badge-secondary float-right" style="background: none;border: 1px solid {{ if eq .Status.Permission "public"}}green{{else}}black{{end}};"> + <i class="fa {{ if eq .Status.Permission "public"}}fa-globe{{else}}fa-user-secret{{end}} mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{ if eq .Status.Permission "public"}}green{{else}}black{{end}};"></i> + <span style="color: {{ if eq .Status.Permission "public"}}green{{else}}black{{end}};">{{ if eq .Status.Permission "public"}}PUBLIC{{else}}CONFIDENTAL{{end}}</span> + </span> + </td> + </tr> + {{end}} + </tbody> + </table> + + + </div> + </div> +</div> + + + +{{template "footer" .}} + + +</body> +</html> diff --git a/web/templates/archive/archive.tmpl b/web/templates/archive/archive.tmpl new file mode 100644 index 0000000..8550d1e --- /dev/null +++ b/web/templates/archive/archive.tmpl @@ -0,0 +1,75 @@ +<!DOCTYPE html> +<html lang="en"> +{{template "head"}} +<body> +{{template "header" .}} + + +<div class="container mb-5"> + <div class="row"> + <div class="col-12"> + + + <h1>Released GLSAs</h1> + + <table id="table_id" class="archives-data-table table table-hover"> + <thead> + <tr> + <th class="hide">ID</th> + <th>GLSA ID</th> + <th>Title</th> + <th>Requester</th> + <th>Date</th> + <th>State</th> + </tr> + </thead> + <tbody> + + {{ range .GLSAs}} + <tr> + <td>{{.Id}}</td> + <td>{{.Alias}}</td> + <td>{{.Title}}</td> + <td>{{.Creator.Nick}}</td> + <td>{{.Created}}</td> + <td> + <span class="badge badge-secondary float-right" style="background: none;border: 1px solid {{ if eq .Status.Permission "public"}}green{{else}}black{{end}};"> + <i class="fa {{ if eq .Status.Permission "public"}}fa-globe{{else}}fa-user-secret{{end}} mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{ if eq .Status.Permission "public"}}green{{else}}black{{end}};"></i> + <span style="color: {{ if eq .Status.Permission "public"}}green{{else}}black{{end}};">{{ if eq .Status.Permission "public"}}PUBLIC{{else}}CONFIDENTAL{{end}}</span> + </span> + + <span class="badge badge-danger float-right mr-2" style="background: none;border: 1px solid {{if eq .Status.WorkflowStatus "commented" }}blue{{else if eq .Status.WorkflowStatus "own"}}green{{else if eq .Status.WorkflowStatus "approved"}}green{{else}}darkred{{end}};"> + <i class="fa {{if eq .Status.WorkflowStatus "commented" }}fa-comments-o{{else if eq .Status.WorkflowStatus "own"}}fa-user{{else if eq .Status.WorkflowStatus "approved"}}fa-check-circle-o{{else}}fa-times-circle{{end}} mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{if eq .Status.WorkflowStatus "commented" }}blue{{else if eq .Status.WorkflowStatus "own"}}green{{else if eq .Status.WorkflowStatus "approved"}}green{{else}}darkred{{end}};"></i> + <span class="text-uppercase" style="color:{{if eq .Status.WorkflowStatus "commented" }}blue{{else if eq .Status.WorkflowStatus "own"}}green{{else if eq .Status.WorkflowStatus "approved"}}green{{else}}darkred{{end}};">{{.Status.WorkflowStatus}}</span> + </span> + + <span class="badge badge-secondary float-right mr-2" style="background: none;border: 1px solid {{if eq .Status.Approval "declined" }}darkred{{else if eq .Status.Approval "approved"}}green{{else if eq .Status.Approval "comments"}}orange{{else}}grey{{end}};"> + <i class="fa fa-circle mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{if eq .Status.Approval "declined" }}darkred{{else if eq .Status.Approval "approved"}}green{{else if eq .Status.Approval "comments"}}orange{{else}}grey{{end}};"></i> + <span class="text-uppercase" style="color:{{if eq .Status.Approval "declined" }}darkred{{else if eq .Status.Approval "approved"}}green{{else if eq .Status.Approval "comments"}}orange{{else}}grey{{end}};">{{.Status.Approval}}</span> + </span> + + <span class="badge badge-secondary float-right mr-2" style="background: none;border: 1px solid {{if .Status.BugReady }}green{{else}}darkred{{end}};padding-top:4px!important;padding-bottom:1.6px;"> + <svg class="" style="width:13px;height:13px" viewBox="0 0 24 24"> + <path fill="{{if .Status.BugReady }}green{{else}}darkred{{end}}" d="M20,8H17.19C16.74,7.2 16.12,6.5 15.37,6L17,4.41L15.59,3L13.42,5.17C12.96,5.06 12.5,5 12,5C11.5,5 11.05,5.06 10.59,5.17L8.41,3L7,4.41L8.62,6C7.87,6.5 7.26,7.21 6.81,8H4V10H6.09C6.03,10.33 6,10.66 6,11V12H4V14H6V15C6,15.34 6.03,15.67 6.09,16H4V18H6.81C8.47,20.87 12.14,21.84 15,20.18C15.91,19.66 16.67,18.9 17.19,18H20V16H17.91C17.97,15.67 18,15.34 18,15V14H20V12H18V11C18,10.66 17.97,10.33 17.91,10H20V8M16,15A4,4 0 0,1 12,19A4,4 0 0,1 8,15V11A4,4 0 0,1 12,7A4,4 0 0,1 16,11V15M14,10V12H10V10H14M10,14H14V16H10V14Z" /> + </svg> + <span class="" style="color:{{if .Status.BugReady }}green{{else}}darkred{{end}};">{{if .Status.BugReady }}READY{{else}}NOT READY{{end}}</span> + </span> + </td> + </tr> + {{end}} + </tbody> + </table> + + + </div> + </div> +</div> + + + +{{template "footer" .}} + +<script src="assets/archive.js"></script> + +</body> +</html> diff --git a/web/templates/authentication/accessDenied.tmpl b/web/templates/authentication/accessDenied.tmpl new file mode 100644 index 0000000..a6042ec --- /dev/null +++ b/web/templates/authentication/accessDenied.tmpl @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html lang="en"> +{{template "head"}} +<body> +{{template "header" .}} + +<div class="container mb-5 text-center pt-5 "> + + <div class="mt-4"></div> + + <i style="font-size: 1000%;" class="fa fa-lock mt-5" aria-hidden="true"></i> + + <h1 class="font-weight-bolder mt-4">- ACCESS DENIED -</h1> + + <h1 style="font-size: 200%; max-width:500px; " class="mx-auto">Sorry, you are missing the necessary rights to access this page.</h1> + + + +</div> + + +{{template "footer" .}} + + +</body> +</html> diff --git a/web/templates/authentication/login.tmpl b/web/templates/authentication/login.tmpl new file mode 100644 index 0000000..b7ec356 --- /dev/null +++ b/web/templates/authentication/login.tmpl @@ -0,0 +1,113 @@ +<!DOCTYPE html> +<html lang="en"> + +<head> + <title>Gentoo Security</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <meta name="theme-color" content="#54487a"> + <meta name="description" content="Gentoo CVE Tool"> + + <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> + + <link rel="icon" href="https://packages.gentoo.org/favicon.ico" type="image/x-icon"> +</head> + +<body style="border-top: none;background: #fff;"> + +<div class="container vh-100 d-flex"> + <div class="row flex-grow-1"> + <div class="col-12 d-flex align-items-center"> + + <div class="row w-100"> + + <div class="col-12 align-items-center"> + <div class="card border-grey mx-auto" style="max-width: 430px;border-color: lightgrey!important;"> + <div class="card-body"> + <div class="text-center" style="margin-top:10px;margin-bottom:20px;"> + <object data="https://www.gentoo.org/assets/img/logo/gentoo-signet.svg" type="image/svg+xml" style="max-width: 80px;"> + <img src="https://assets.gentoo.org/tyrian/site-logo.png" alt="Gentoo Linux logo"> + </object> + </div> + + <form name="login" action="/login" method="POST"> + + <div class="row"> + <div class="col-12" style="padding-bottom:20px!important;padding-left:50px!important;padding-right:50px!important;"> + <label for="username" class="d-none">Username:</label> + <input style="border-top: none;border-left: none; border-right: none; border-radius: 0px;" placeholder="Username" size="35" id="username" name="username" class="form-control" type="text" autofocus="" required=""> + </div> + <div class="col-12" style="padding-bottom:20px!important;padding-left:50px!important;padding-right:50px!important;"> + <label for="password" class="d-none">Password:</label> + <input style="border-top: none;border-left: none; border-right: none; border-radius: 0px;" type="password" size="35" id="password" name="password" placeholder="Password" class="form-control" required=""> + </div> + <div class="col-12" style="padding-bottom:20px!important;padding-left:50px!important;padding-right:50px!important;"> + <input type="checkbox" id="restrictlogin" name="restrictlogin" checked="checked"> + <small class="text-muted">Restrict this session to this IP address + (using this option improves security)</small> + </div> + <div class="col-12"> + <input style="display: none;" name="cameFrom" id="cameFrom" value="{{ .CameFrom }}" /> + </div> + + + <div class="col-12 mt-3" style="padding-bottom:10px; padding-right:50px; padding-left:50px; width:100%;"> + <div class="text-right"style="width:100%;"> + <input type="submit" class="btn btn-primary" name="GoAheadAndLogIn" style="border-color: #54487A!important;background-color: #54487A!important;" value="Log in" id="log_in"> + </div> + </div> + + <div class="col-12 d-none" style="padding-right:50px; padding-left: 50px; width:100%;"> + <hr> + </div> + </div> + + + </form> + + </div> + </div> + </div> + + <div class="col-12 mt-3 align-items-center"> + <div class="card border-0 text-right text-muted mx-auto" style="max-width: 430px;"> + <span class="" style="font-size: 80%;"> + <a class="mr-4 text-muted" style="text-decoration: none;" data-toggle="collapse" href="#create-new-account-notice" role="button" aria-expanded="false" aria-controls="multiCollapseExample1">New Account</a> + <a class="text-muted" style="text-decoration: none;" data-toggle="collapse" href="#reset-password-notice" role="button" aria-expanded="false" aria-controls="multiCollapseExample1">Reset Password</a> + </span> + + + + <div class="card-body"> + <div class="collapse mt-2" id="create-new-account-notice"> + <div class="card card-body border-0 p-0"> + <small>To create a new account, please contact the security team and request access.</small> + </div> + </div> + + <div class="collapse mt-2" id="reset-password-notice"> + <div class="card card-body border-0 p-0"> + <small>In case you've forgotten your password, please contact the security team and ask an admin to reset your password.</small> + </div> + </div> + </div> + + </div> + </div> + + </div> + </div> + + + + </div> +</div> + + +<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script> +<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> + + +</body> +</html> diff --git a/web/templates/authentication/totp.tmpl b/web/templates/authentication/totp.tmpl new file mode 100644 index 0000000..ea1871c --- /dev/null +++ b/web/templates/authentication/totp.tmpl @@ -0,0 +1,94 @@ +<!DOCTYPE html> +<html lang="en"> + +<head> + <title>Gentoo Security</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <meta name="theme-color" content="#54487a"> + <meta name="description" content="Gentoo CVE Tool"> + + <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> + + <link rel="icon" href="https://packages.gentoo.org/favicon.ico" type="image/x-icon"> +</head> + +<body style="border-top: none;background: #fff;"> + +<div class="container vh-100 d-flex"> + <div class="row flex-grow-1"> + <div class="col-12 d-flex align-items-center"> + + <div class="row w-100"> + + <div class="col-12 align-items-center"> + <div class="card border-grey mx-auto" style="max-width: 430px;border-color: lightgrey!important;"> + <div class="card-body"> + <div class="text-center" style="margin-top:10px;margin-bottom:20px;"> + <object data="https://www.gentoo.org/assets/img/logo/gentoo-signet.svg" type="image/svg+xml" style="max-width: 80px;"> + <img src="https://assets.gentoo.org/tyrian/site-logo.png" alt="Gentoo Linux logo"> + </object> + <h4 class="mt-2">TOTP Login</h4> + </div> + + <form name="login" action="/login/2fa/totp" method="POST"> + + <div class="row mt-5 pt-3"> + <div class="col-12" style="padding-bottom:20px!important;padding-left:80px!important;padding-right:80px!important;"> + <input placeholder="One-time Password" type="text" maxlength="6" size="35" id="token" name="token" class="form-control" required=""> + </div> + + <input style="display: none;" name="cameFrom" id="cameFrom" value="{{ .CameFrom }}" /> + + </div> + + <div class="text-right mt-3" style="width:100%;"> + <input type="submit" class="btn btn-primary" style="border-color: #54487A!important;background-color: #54487A!important;" name="GoAheadAndLogIn" value="Log in" id="log_in"> + </div> + </form> + + </div> + </div> + </div> + + <div class="col-12 mt-3 align-items-center"> + <div class="card border-0 text-right text-muted mx-auto" style="max-width: 430px;"> + <span class="" style="font-size: 80%;"> + <a class="mr-4 text-muted" style="text-decoration: none;" data-toggle="collapse" href="#help-notice" role="button" aria-expanded="false" aria-controls="multiCollapseExample1">Help</a> + <a class="text-muted" style="text-decoration: none;" data-toggle="collapse" href="#reset-notice" role="button" aria-expanded="false" aria-controls="multiCollapseExample1">Lost my Authenticators</a> + </span> + + + + <div class="card-body"> + <div class="collapse mt-2" id="help-notice"> + <div class="card card-body border-0 p-0"> + <small>You've activated 2FA using TOTP for your account. Please use one of your registered Authenticators to generate a TOTP and log in.</small> + </div> + </div> + + <div class="collapse mt-2" id="reset-notice"> + <div class="card card-body border-0 p-0"> + <small>In case you lost all authenticators that you have registered, please contact the security team and ask an admin to temporarly disabled WebAuthn for your account.</small> + </div> + </div> + </div> + + </div> + </div> + + </div> + </div> + + + + </div> +</div> + +<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script> +<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> + + +</body> +</html> diff --git a/web/templates/authentication/webauthn.tmpl b/web/templates/authentication/webauthn.tmpl new file mode 100644 index 0000000..03a92f8 --- /dev/null +++ b/web/templates/authentication/webauthn.tmpl @@ -0,0 +1,204 @@ +<!DOCTYPE html> +<html lang="en"> + +<head> + <title>Gentoo Security</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <meta name="theme-color" content="#54487a"> + <meta name="description" content="Gentoo CVE Tool"> + + <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> + + <link rel="icon" href="https://packages.gentoo.org/favicon.ico" type="image/x-icon"> +</head> + +<body style="border-top: none;background: #fff;"> + +<div class="container vh-100 d-flex"> + <div class="row flex-grow-1"> + <div class="col-12 d-flex align-items-center"> + + <div class="row w-100"> + + <div class="col-12 align-items-center"> + <div class="card border-grey mx-auto" style="max-width: 430px;border-color: lightgrey!important;"> + <div class="card-body"> + <div class="text-center" style="margin-top:10px;margin-bottom:20px;"> + <object data="https://www.gentoo.org/assets/img/logo/gentoo-signet.svg" type="image/svg+xml" style="max-width: 80px;"> + <img src="https://assets.gentoo.org/tyrian/site-logo.png" alt="Gentoo Linux logo"> + </object> + <h4 class="mt-2">WebAuthn Login</h4> + </div> + + <div id="result-success" class="alert alert-success" role="alert" style="margin-left:40px!important;margin-right:40px!important;display:none;"> + Successfully authenticated. + </div> + + <div id="result-error" class="alert alert-danger" role="alert" style="margin-left:40px!important;margin-right:40px!important;display:none;"> + Error during the authentication. + </div> + + <table class="mb-5 mt-5"> + <tbody> + <tr> + <td id="authentication-notice" style="padding-bottom:10px!important;padding-left:20px!important;padding-right:20px!important;"> + <span>2FA using WebAuthn is activated. Please use your authenticator to log in.</span> + </td> + </tr> + + <input style="display: none;" name="cameFrom" id="cameFrom" value="{{ .CameFrom }}" /> + + </tbody> + </table> + + + <div id="start-btn" class="text-right" style="width:100%;"> + <button class="btn btn-primary" style="border-color: #54487A!important;background-color: #54487A!important;" onclick="document.getElementById('start-btn').style.display='none';loginUser();">Start</button> + </div> + + <div id="continue-btn" class="text-right" style="width:100%;display: none;"> + <a href="/" class="btn btn-outline-success">Continue</a> + </div> + + <div id="retry-btn" class="text-right" style="width:100%;display: none;"> + <button class="btn btn-outline-danger" onclick="document.getElementById('start-btn').style.display='none';loginUser();">Retry</button> + </div> + + </div> + </div> + </div> + + <div class="col-12 mt-3 align-items-center"> + <div class="card border-0 text-right text-muted mx-auto" style="max-width: 430px;"> + <span class="" style="font-size: 80%;"> + <a class="mr-4 text-muted" style="text-decoration: none;" data-toggle="collapse" href="#help-notice" role="button" aria-expanded="false" aria-controls="multiCollapseExample1">Help</a> + <a class="text-muted" style="text-decoration: none;" data-toggle="collapse" href="#reset-notice" role="button" aria-expanded="false" aria-controls="multiCollapseExample1">Lost my Authenticators</a> + </span> + + + + <div class="card-body"> + <div class="collapse mt-2" id="help-notice"> + <div class="card card-body border-0 p-0"> + <small>You've activated 2FA using WebAuthn for your account. Please use one of your registered Authenticators (such as security keys) to log in.</small> + </div> + </div> + + <div class="collapse mt-2" id="reset-notice"> + <div class="card card-body border-0 p-0"> + <small>In case you lost all authenticators that you have registered, please contact the security team and ask an admin to temporarly disabled WebAuthn for your account.</small> + </div> + </div> + </div> + + </div> + </div> + + </div> + </div> + + + + </div> +</div> + + +<script + src="https://code.jquery.com/jquery-3.4.1.min.js" + integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" + crossorigin="anonymous"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script> +<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> + + +<script> + + // Base64 to ArrayBuffer + function bufferDecode(value) { + return Uint8Array.from(atob(value), c => c.charCodeAt(0)); + } + + // ArrayBuffer to URLBase64 + function bufferEncode(value) { + return btoa(String.fromCharCode.apply(null, new Uint8Array(value))) + .replace(/\+/g, "-") + .replace(/\//g, "_") + .replace(/=/g, ""); + } + + + function loginUser() { + $.post( + '/login/2fa/webauthn/begin', + JSON.stringify({ + cameFrom: {{ .CameFrom }}, + restrictlogin: "on", + }), + function (data) { + return data + }, + 'json') + .then((credentialRequestOptions) => { + //alert("First step done"); + console.log(credentialRequestOptions); + credentialRequestOptions.publicKey.challenge = bufferDecode(credentialRequestOptions.publicKey.challenge); + credentialRequestOptions.publicKey.allowCredentials.forEach(function (listItem) { + listItem.id = bufferDecode(listItem.id) + }); + + return navigator.credentials.get({ + publicKey: credentialRequestOptions.publicKey + }) + }) + .then((assertion) => { + //alert("Second step done"); + console.log(assertion); + let authData = assertion.response.authenticatorData; + let clientDataJSON = assertion.response.clientDataJSON; + let rawId = assertion.rawId; + let sig = assertion.response.signature; + let userHandle = assertion.response.userHandle; + + $.post( + '/login/2fa/webauthn/finish', + JSON.stringify({ + cameFrom: {{ .CameFrom }}, + restrictlogin: "on", + id: assertion.id, + rawId: bufferEncode(rawId), + type: assertion.type, + response: { + authenticatorData: bufferEncode(authData), + clientDataJSON: bufferEncode(clientDataJSON), + signature: bufferEncode(sig), + userHandle: bufferEncode(userHandle), + }, + }), + function (data) { + return data + }, + 'json') + }) + .then((success) => { + document.getElementById('authentication-notice').style.display='none'; + document.getElementById('retry-btn').style.display='none'; + document.getElementById('result-success').style.display='block'; + document.getElementById('result-error').style.display='none'; + document.getElementById('continue-btn').style.display='inline-block'; + return + }) + .catch((error) => { + document.getElementById('authentication-notice').style.display='none'; + document.getElementById('result-success').style.display='none'; + document.getElementById('result-error').style.display='block'; + document.getElementById('retry-btn').style.display='inline-block'; + return + }) + } + +</script> + + +</body> +</html> diff --git a/web/templates/dashboard/dashboard.tmpl b/web/templates/dashboard/dashboard.tmpl new file mode 100644 index 0000000..d77fd73 --- /dev/null +++ b/web/templates/dashboard/dashboard.tmpl @@ -0,0 +1,158 @@ +<!DOCTYPE html> +<html lang="en"> +{{template "head"}} +<body> +{{template "header" .}} + +<style> + #bar > svg{ + display:block; + } + #bar{ + width:100%; + height:180px; + margin:0; + padding: 0; + } +</style> + +<div class="container mb-5"> + + + <h1>Dashboard</h1> + <hr/> + + <div class="row mt-2 pb-3 d-none"><div class="col-12"><hr/></div></div> + + <div class="row mt-4"> + <div class="col-xs-12 col-md-6"> + <h2>Requests & Drafts <small class="text-muted" style="font-size: 16px;">recently created</small></h2> + <table class="table table frontpage-table"> + + <tbody> + + {{range .GLSAs}} + <tr> + <td class="text-left"><span class="badge {{if eq .Type "request"}}badge-danger{{else if eq .Type "draft"}}badge-warning{{else}}badge-success{{end}} text-capitalize">{{.Type}}</span></td> + <td><a href="/glsa/{{.Id}}" rel="nofollow" title="{{.Title}}">{{.Title}}</a></td> + <td class="frontpage-table-planet-author">{{.Creator.Nick}}</td> + </tr> + {{end}} + + </tbody></table> + </div> + <div class="col-xs-12 col-md-6"> + <h2>Recent Statistics <small class="text-muted" style="font-size: 16px;">from our <a href="/statistics">Statistics Page</a></small></h2> + <div id="bar"></div> + </div> + </div> + + <div class="row mt-4"> + <div class="col-xs-12 col-md-6"> + <h2>Recent CVEs <small class="text-muted" style="font-size: 16px;">view more at the <a href="/cve/tool">CVE Tool</a></small></h2> + <table class="table frontpage-table"> + + <tbody> + + {{range .CVEs}} + <tr> + <td class="frontpage-table-planet-author">{{.Id}}</td> + <td style="max-height: 30px; overflow-y: hidden; display: block;text-overflow: ellipsis;"><a href="#" rel="nofollow" title="{{.Description}}">{{.Description}}</a></td> + <td class="frontpage-table-planet-author">{{.LastModifiedDate}}</td> + </tr> + {{end}} + + </tbody></table> + </div> + <div class="col-xs-12 col-md-6"> + <h2>Recent Comments <small class="text-muted" style="font-size: 16px;"> on <a href="/all">GLSAs</a> and <a href="/cve/tool">CVEs</a></small></h2> + <table class="table "> + + <tbody> + + {{range .Comments}} + <tr> + <td> + {{if .GlsaId}} + <span class="badge badge-{{if eq .Type "approve"}}success{{else if eq .Type "decline"}}danger{{else}}primary{{end}}"> + GLSA <span class="text-capitalize">{{if eq .Type "approve"}}{{.Type}}{{else if eq .Type "decline"}}{{.Type}}{{else}}{{end}}</span> + </span> + {{else}} + <span class="badge badge-info"> + CVE + </span> + {{end}} + </td> + <td> + <a href="{{if .GlsaId}}/glsa/{{.GlsaId}}{{end}}">{{.Message}}</a> + </td> + <td class="text-right"> + {{.User}} + </td> + <td class="text-right"> + {{.Date}} + </td> + </tr> + {{end}} + + </tbody></table> + </div> + </div> + + +</div> + + + +{{template "footer" .}} + + +<script> + window.CHART_DATA = [ + { + type: 'GLSAs', + stage: 'request', + count: {{.StatisticsData.Requests}}, + }, + { + type: 'GLSAs', + stage: 'draft', + count: {{.StatisticsData.Drafts}}, + }, + { + type: 'GLSAs', + stage: 'glsa', + count: {{.StatisticsData.Glsas}}, + }, + { + type: 'CVEs', + stage: 'New', + count: {{.StatisticsData.New}}, + }, + { + type: 'CVEs', + stage: 'Assigned', + count: {{.StatisticsData.Assigned}}, + }, + { + type: 'CVEs', + stage: 'Later', + count: {{.StatisticsData.Later}}, + }, + { + type: 'CVEs', + stage: 'NFU', + count: {{.StatisticsData.NFU}}, + }, + { + type: 'CVEs', + stage: 'Invalid', + count: {{.StatisticsData.Invalid}}, + } + ]; +</script> + +<script src="/assets/statistics.js"></script> + +</body> +</html> diff --git a/web/templates/drafts/drafts.tmpl b/web/templates/drafts/drafts.tmpl new file mode 100644 index 0000000..e0e5c10 --- /dev/null +++ b/web/templates/drafts/drafts.tmpl @@ -0,0 +1,84 @@ +<!DOCTYPE html> +<html lang="en"> +{{template "head"}} +<body> +{{template "header" .}} + +<style> + td:hover { + cursor: pointer; + } +</style> + +<div class="container mb-5"> + <div class="row"> + <div class="col-12"> + + + <h1>Drafts</h1> + + <table id="table_id" class="drafts-data-table table table-hover"> + <thead> + <tr> + <th>ID</th> + <th>Title</th> + <th>Requester</th> + <th>Date</th> + <th>Bug Ready</th> + <th>Approved</th> + <th>Workflow</th> + <th>Permissions</th> + </tr> + </thead> + <tbody> + + {{ range .Drafts}} + <tr> + <td>{{.Id}}</td> + <td>{{.Title}}</td> + <td>{{.Creator.Nick}}</td> + <td>{{.Created}}</td> + <td> + <span class="badge badge-secondary float-right mr-2" style="background: none;border: 1px solid {{if .Status.BugReady }}green{{else}}darkred{{end}};padding-top:4px!important;padding-bottom:1.6px;"> + <svg class="" style="width:13px;height:13px" viewBox="0 0 24 24"> + <path fill="{{if .Status.BugReady }}green{{else}}darkred{{end}}" d="M20,8H17.19C16.74,7.2 16.12,6.5 15.37,6L17,4.41L15.59,3L13.42,5.17C12.96,5.06 12.5,5 12,5C11.5,5 11.05,5.06 10.59,5.17L8.41,3L7,4.41L8.62,6C7.87,6.5 7.26,7.21 6.81,8H4V10H6.09C6.03,10.33 6,10.66 6,11V12H4V14H6V15C6,15.34 6.03,15.67 6.09,16H4V18H6.81C8.47,20.87 12.14,21.84 15,20.18C15.91,19.66 16.67,18.9 17.19,18H20V16H17.91C17.97,15.67 18,15.34 18,15V14H20V12H18V11C18,10.66 17.97,10.33 17.91,10H20V8M16,15A4,4 0 0,1 12,19A4,4 0 0,1 8,15V11A4,4 0 0,1 12,7A4,4 0 0,1 16,11V15M14,10V12H10V10H14M10,14H14V16H10V14Z" /> + </svg> + <span class="" style="color:{{if .Status.BugReady }}green{{else}}darkred{{end}};">{{if .Status.BugReady }}READY{{else}}NOT READY{{end}}</span> + </span> + + </td> + <td> + <span class="badge badge-secondary float-right mr-2" style="background: none;border: 1px solid {{if eq .Status.Approval "declined" }}darkred{{else if eq .Status.Approval "approved"}}green{{else if eq .Status.Approval "comments"}}orange{{else}}grey{{end}};"> + <i class="fa fa-circle mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{if eq .Status.Approval "declined" }}darkred{{else if eq .Status.Approval "approved"}}green{{else if eq .Status.Approval "comments"}}orange{{else}}grey{{end}};"></i> + <span class="text-uppercase" style="color:{{if eq .Status.Approval "declined" }}darkred{{else if eq .Status.Approval "approved"}}green{{else if eq .Status.Approval "comments"}}orange{{else}}grey{{end}};">{{.Status.Approval}}</span> + </span> + </td> + <td> + <span class="badge badge-danger float-right mr-2" style="background: none;border: 1px solid {{if eq .Status.WorkflowStatus "commented" }}blue{{else if eq .Status.WorkflowStatus "own"}}green{{else if eq .Status.WorkflowStatus "approved"}}green{{else}}darkred{{end}};"> + <i class="fa {{if eq .Status.WorkflowStatus "commented" }}fa-comments-o{{else if eq .Status.WorkflowStatus "own"}}fa-user{{else if eq .Status.WorkflowStatus "approved"}}fa-check-circle-o{{else}}fa-times-circle{{end}} mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{if eq .Status.WorkflowStatus "commented" }}blue{{else if eq .Status.WorkflowStatus "own"}}green{{else if eq .Status.WorkflowStatus "approved"}}green{{else}}darkred{{end}};"></i> + <span class="text-uppercase" style="color:{{if eq .Status.WorkflowStatus "commented" }}blue{{else if eq .Status.WorkflowStatus "own"}}green{{else if eq .Status.WorkflowStatus "approved"}}green{{else}}darkred{{end}};">{{.Status.WorkflowStatus}}</span> + </span> + </td> + <td> + <span class="badge badge-secondary float-right" style="background: none;border: 1px solid {{ if eq .Status.Permission "public"}}green{{else}}black{{end}};"> + <i class="fa {{ if eq .Status.Permission "public"}}fa-globe{{else}}fa-user-secret{{end}} mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{ if eq .Status.Permission "public"}}green{{else}}black{{end}};"></i> + <span style="color: {{ if eq .Status.Permission "public"}}green{{else}}black{{end}};">{{ if eq .Status.Permission "public"}}PUBLIC{{else}}CONFIDENTAL{{end}}</span> + </span> + </td> + </tr> + {{end}} + </tbody> + </table> + + + </div> + </div> +</div> + + +{{template "footer" .}} + +<script src="assets/drafts.js"></script> + +</body> +</html> diff --git a/web/templates/glsa/edit.tmpl b/web/templates/glsa/edit.tmpl new file mode 100644 index 0000000..4318d86 --- /dev/null +++ b/web/templates/glsa/edit.tmpl @@ -0,0 +1,768 @@ +<!DOCTYPE html> +<html lang="en"> +{{template "head"}} +<body> +{{template "header" .}} + +<form id="glsa_edit" action="/glsa/edit/{{.Glsa.Id}}" method="POST"> + + <div class="container mb-5 mt-2"> + <div class="row"> + + + <div class="col-sm-12" style="margin-bottom:10px;"> + <small> + <div class="navigation"> + <a href="/all"><b>GLSA List:</b></a> + + ({{.Glsa.Id}} of {{.GlsaCount}}) + + {{ if eq 1 .Glsa.Id }} + <span class="navigation_link"><i class="fa fa-angle-double-left" aria-hidden="true"></i> First</span> + {{else}} + <a href="/glsa/1" class="navigation_link" style="font-style: normal;"><i class="fa fa-angle-double-left" aria-hidden="true"></i> First</a> + {{end}} + + {{ if eq (prevGLSA .Glsa.Id 1) .Glsa.Id }} + <span class="navigation_link"><i class="fa fa-angle-left" aria-hidden="true"></i> Prev</span> + {{else}} + <a href="/glsa/{{prevGLSA .Glsa.Id .GlsaCount}}" class="navigation_link" style="font-style: normal;"><i class="fa fa-angle-left" aria-hidden="true"></i> Prev</a> + {{end}} + + {{ if eq (nextGLSA .Glsa.Id .GlsaCount) .Glsa.Id }} + <span class="navigation_link">Next <i class="fa fa-angle-right" aria-hidden="true"></i></span> + {{else}} + <a href="/glsa/{{nextGLSA .Glsa.Id .GlsaCount}}" class="navigation_link" style="font-style: normal;">Next <i class="fa fa-angle-right" aria-hidden="true"></i></a> + {{end}} + + {{ if eq .GlsaCount .Glsa.Id }} + <span class="navigation_link" style="">Last <i class="fa fa-angle-double-right" aria-hidden="true"></i></span> + {{else}} + <a href="/glsa/{{.GlsaCount}}" class="navigation_link" style="font-style: normal;">Last <i class="fa fa-angle-double-right" aria-hidden="true"></i></a> + {{end}} + + + <button type="submit" class="float-right btn btn-success btn-sm">Save GLSA</button> + + <a href="/glsa/{{.Glsa.Id}}" class="float-right btn btn-outline-danger btn-sm" style="margin-right:5px;">Cancel</a> + + + </div> + </small> + </div> + + <div class="col-12 mt-2"> + + + <div class="card"> + <div class="card-body"> + <div class="row"> + + <div class="col-sm-12"> + <span class="badge {{if eq .Glsa.Type "request"}}badge-danger{{else if eq .Glsa.Type "draft"}}badge-warning{{else}}badge-success{{end}} text-capitalize">{{.Glsa.Type}}</span> + <a style="color:#000000;" href="/glsa/{{.Glsa.Id}}">GLSA <span id="glsa-id">{{.Glsa.Id}}</span></a> + + <span id="summary_container"> + <small style="margin-left:5px;color:#505152;">Created: {{.Glsa.Created}}</small> + <small style="margin-left:5px;color:#505152;">Updated: {{.Glsa.Updated}}</small> + </span> + + + + <span class="badge badge-secondary float-right" style="background: none;border: 1px solid {{ if eq .Glsa.Status.Permission "public"}}green{{else}}black{{end}};"> + <i class="fa {{ if eq .Glsa.Status.Permission "public"}}fa-globe{{else}}fa-user-secret{{end}} mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{ if eq .Glsa.Status.Permission "public"}}green{{else}}black{{end}};"></i> + <span style="color: {{ if eq .Glsa.Permission "public"}}green{{else}}black{{end}};">{{ if eq .Glsa.Status.Permission "public"}}PUBLIC{{else}}CONFIDENTAL{{end}}</span> + </span> + + <span class="badge badge-danger float-right mr-2" style="background: none;border: 1px solid {{if eq .Glsa.Status.WorkflowStatus "commented" }}blue{{else if eq .Glsa.Status.WorkflowStatus "own"}}green{{else if eq .Glsa.Status.WorkflowStatus "approved"}}green{{else}}darkred{{end}};"> + <i class="fa {{if eq .Glsa.Status.WorkflowStatus "commented" }}fa-comments-o{{else if eq .Glsa.Status.WorkflowStatus "own"}}fa-user{{else if eq .Glsa.Status.WorkflowStatus "approved"}}fa-check-circle-o{{else}}fa-times-circle{{end}} mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{if eq .Glsa.Status.WorkflowStatus "commented" }}blue{{else if eq .Glsa.Status.WorkflowStatus "own"}}green{{else if eq .Glsa.Status.WorkflowStatus "approved"}}green{{else}}darkred{{end}};"></i> + <span class="text-uppercase" style="color:{{if eq .Glsa.Status.WorkflowStatus "commented" }}blue{{else if eq .Glsa.Status.WorkflowStatus "own"}}green{{else if eq .Glsa.Status.WorkflowStatus "approved"}}green{{else}}darkred{{end}};">{{.Glsa.Status.WorkflowStatus}}</span> + </span> + + <span class="badge badge-secondary float-right mr-2" style="background: none;border: 1px solid {{if eq .Glsa.Status.Approval "declined" }}darkred{{else if eq .Glsa.Status.Approval "approved"}}green{{else if eq .Glsa.Status.Approval "comments"}}orange{{else}}grey{{end}};"> + <i class="fa fa-circle mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{if eq .Glsa.Status.Approval "declined" }}darkred{{else if eq .Glsa.Status.Approval "approved"}}green{{else if eq .Glsa.Status.Approval "comments"}}orange{{else}}grey{{end}};"></i> + <span class="text-uppercase" style="color:{{if eq .Glsa.Status.Approval "declined" }}darkred{{else if eq .Glsa.Status.Approval "approved"}}green{{else if eq .Glsa.Status.Approval "comments"}}orange{{else}}grey{{end}};">{{.Glsa.Status.Approval}}</span> + </span> + + <span class="badge badge-secondary float-right mr-2" style="background: none;border: 1px solid {{if .Glsa.Status.BugReady }}green{{else}}darkred{{end}};padding-top:4px!important;padding-bottom:1.6px;"> + <svg class="" style="width:13px;height:13px" viewBox="0 0 24 24"> + <path fill="{{if .Glsa.Status.BugReady }}green{{else}}darkred{{end}}" d="M20,8H17.19C16.74,7.2 16.12,6.5 15.37,6L17,4.41L15.59,3L13.42,5.17C12.96,5.06 12.5,5 12,5C11.5,5 11.05,5.06 10.59,5.17L8.41,3L7,4.41L8.62,6C7.87,6.5 7.26,7.21 6.81,8H4V10H6.09C6.03,10.33 6,10.66 6,11V12H4V14H6V15C6,15.34 6.03,15.67 6.09,16H4V18H6.81C8.47,20.87 12.14,21.84 15,20.18C15.91,19.66 16.67,18.9 17.19,18H20V16H17.91C17.97,15.67 18,15.34 18,15V14H20V12H18V11C18,10.66 17.97,10.33 17.91,10H20V8M16,15A4,4 0 0,1 12,19A4,4 0 0,1 8,15V11A4,4 0 0,1 12,7A4,4 0 0,1 16,11V15M14,10V12H10V10H14M10,14H14V16H10V14Z" /> + </svg> + <span class="" style="color:{{if .Glsa.Status.BugReady }}green{{else}}darkred{{end}};">{{if .Glsa.Status.BugReady }}READY{{else}}NOT READY{{end}}</span> + </span> + + + + </div> + + <div class="col-sm-12"> + <h1 style="font-size: 20px;margin-top:10px;margin-bottom:4px;"><span id="short_desc_nonedit_display"> + <input class="form-control p-2" type="text" name="title" value="{{.Glsa.Title}}" style="font-weight: 800; font-size: large; height: 30px;padding: .25rem .5rem;display: inline-block" /> + </span></h1> + </div> + </div> + </div> + </div> + </div> + + + <div class="col-12 mt-4"> + + <div class="card"> + <div class="card-header" style="padding-left: 8px; padding-right: 8px; padding-top: 4px; padding-bottom: 4px;font-weight:bold;font-size:13px;"> + <a data-toggle="collapse" href="#collapseMetadata" style="outline : none;text-decoration: none;color:#000;" onclick="this.getElementsByTagName('i')[0].classList.toggle('fa-caret-down');this.getElementsByTagName('i')[0].classList.toggle('fa-caret-right');"> + <i class="fa fa-caret-down" aria-hidden="true" style="margin-right:5px;cursor: pointer"></i> Metadata</a> + </div> + <div class="card-body collapse show" id="collapseMetadata"> + <div class="row"> + <div class="col-sm-3"> + <small class="mr-2 text-uppercase text-muted" style="font-size: 12px;"><i class="fa fa-unlock" aria-hidden="true"></i> Permission:</small> + <small style="font-size: 12px;"> + <select name="permission" class="custom-select" style="display: inline-block;max-width: 100px;height: 30px;padding: .25rem .5rem;"> + <option value="public" {{if eq .Glsa.Permission "public"}}selected{{end}}>public</option> + <option value="confidential" {{if eq .Glsa.Permission "confidential"}}selected{{end}}>confidential</option> + </select> + </small> + </div> + <div class="col-sm-3"> + <small class="mr-2 text-uppercase text-muted" style="font-size: 12px;"><i class="fa fa-address-card" aria-hidden="true"></i> Access: </small> + <small style="font-size: 12px;"> + <select name="access" class="custom-select" style="display: inline-block;max-width: 150px;height: 30px;padding: .25rem .5rem;"> + <option value="local" {{if eq .Glsa.Access "local"}}selected{{end}}>local</option> + <option value="remote" {{if eq .Glsa.Access "remote"}}selected{{end}}>remote</option> + <option value="local,remote" {{if eq .Glsa.Access "local,remote"}}selected{{end}}>local, remote</option> + </select> + </small> + </div> + + <div class="col-sm-3"> + <small class="mr-2 text-uppercase text-muted" style="font-size: 12px;"><i class="fa fa-balance-scale" aria-hidden="true"></i> Severity: </small> + <small style="font-size: 12px;"> + <select name="severity" class="custom-select" style="display: inline-block;max-width: 100px;height: 30px;padding: .25rem .5rem;"> + <option value="low" {{if eq .Glsa.Severity "low"}}selected{{end}}>low</option> + <option value="normal" {{if eq .Glsa.Severity "normal"}}selected{{end}}>normal</option> + <option value="high" {{if eq .Glsa.Severity "high"}}selected{{end}}>high</option> + </select> + </small> + </div> + <div class="col-sm-3"> + <small class="mr-2 text-uppercase text-muted" style="font-size: 12px;"><i class="fa fa-tag" aria-hidden="true"></i> Keyword:</small> + <small style="font-size: 12px;"> + <input name="keyword" class="form-control" type="text" value="{{.Glsa.Keyword}}" style="max-width: 150px;height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + </div> + + </div> + </div> + </div> + + </div> + + + <div class="col-12 mt-4"> + <div class="card"> + <div class="card-header" style="padding-left: 8px; padding-right: 8px; padding-top: 4px; padding-bottom: 4px;font-weight:bold;font-size:13px;"> + <a data-toggle="collapse" href="#collapseOverview" style="outline : none;text-decoration: none;color:#000;" onclick="this.getElementsByTagName('i')[0].classList.toggle('fa-caret-down');this.getElementsByTagName('i')[0].classList.toggle('fa-caret-right');"> + <i class="fa fa-caret-down" aria-hidden="true" style="margin-right:5px;cursor: pointer"></i> Overview</a> + </div> + <div class="card-body collapse show" id="collapseOverview"> + <div class="row"> + + <div class="col-sm-12"> + <div class="row" style="margin-bottom:2px;"> + <div class="col-md-auto align-h-right" style="min-width: 125px;padding-right:0px;color:#505050;"> + <small class="text-uppercase text-muted" style="font-size: 12px;"><i class="fa fa-sticky-note-o" aria-hidden="true"></i> Synopsis:</small> + </div> + <div class="col" style="color:#292929;padding-left:10px;"> + <small style="font-size: 12px;"> + <input name="synopsis" class="form-control" type="text" value="{{.Glsa.Synopsis}}" style="height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + </div> + </div> + </div> + + <div class="col-sm-12"> + <div class="row mt-3" style="margin-bottom:2px;"> + <div class="col-6" style="margin-bottom:2px;"> + <div class="row"> + <div class="col-md-auto align-h-right" style="min-width: 125px; padding-right:0px;color:#505050;"> + <small class="text-uppercase text-muted" style="font-size: 12px;"><i class="fa fa-file-text-o" aria-hidden="true"></i> Description:</small> + </div> + <div class="col" style="color:#292929;padding-left:10px;"> + <small style="font-size: 12px;"> + <textarea name="description" style="" rows="3" onfocusin="this.rows=5" onfocusout="this.rows=3" class="form-control">{{.Glsa.Description}}</textarea> + </small> + </div> + </div> + </div> + + <div class="col-6"> + <div class="row"> + <div class="col-md-auto" style="min-width: 125px; padding-right:0px;color:#505050;"> + <small class="text-uppercase text-muted" style="font-size: 12px;"><i class="fa fa-medkit" aria-hidden="true"></i> Workaround:</small> + </div> + <div class="col" style="color:#292929;padding-left:10px;"> + <textarea name="workaround" rows="3" onfocusin="this.rows=5" onfocusout="this.rows=3" class="form-control">{{.Glsa.Workaround}}</textarea> + </div> + </div> + </div> + </div> + </div> + + <div class="col-12"> + <div class="row mt-3 equal"> + <div class="col-6"> + <div class="row"> + <div class="col-md-auto" style="min-width: 125px; padding-right:0px;color:#505050;"> + <small class="text-uppercase text-muted" style="font-size: 12px;"><i class="fa fa-bullseye" aria-hidden="true"></i> Impact:</small> + </div> + <div class="col" style="color:#292929;padding-left:10px;"> + <textarea name="impact" rows="3" onfocusin="this.rows=5" onfocusout="this.rows=3" class="form-control">{{.Glsa.Impact}}</textarea> + </div> + </div> + </div> + + <div class="col-6"> + <div class="row" style="padding-right:0px;color:#505050;"> + <div class="col-md-auto align-h-right" style="min-width: 125px;padding-right:0px;color:#505050;"> + <small class="text-uppercase text-muted" style="font-size: 12px;"><i class="fa fa-align-right" aria-hidden="true"></i> Background:</small> + </div> + <div class="col" style="color:#292929;padding-left:10px;"> + <textarea name="background" rows="3" onfocusin="this.rows=5" onfocusout="this.rows=3" class="form-control">{{.Glsa.Background}}</textarea> + </div> + </div> + </div> + </div> + </div> + + </div> + </div> + </div> + </div> + + + <div class="col-12 mt-4"> + <div class="card"> + <div class="card-header" style="padding-left: 8px; padding-right: 8px; padding-top: 4px; padding-bottom: 4px;font-weight:bold;font-size:13px;"> + <a data-toggle="collapse" href="#collapseResolution" style="outline : none;text-decoration: none;color:#000;" onclick="this.getElementsByTagName('i')[0].classList.toggle('fa-caret-down');this.getElementsByTagName('i')[0].classList.toggle('fa-caret-right');"> + <i class="fa fa-caret-down" aria-hidden="true" style="margin-right:5px;cursor: pointer"></i> Resolution</a> + </div> + <div class="card-body collapse show" id="collapseResolution"> + <textarea name="resolution" rows="7" onfocusin="this.rows=10" onfocusout="this.rows=7" class="form-control">{{.Glsa.Resolution}}</textarea> + </div> + </div> + </div> + + + + <div class="col-12 mt-4"> + <div class="card"> + <div class="card-header" style="padding-left: 8px; padding-right: 8px; padding-top: 4px; padding-bottom: 4px;font-weight:bold;font-size:13px;"> + <a data-toggle="collapse" href="#collapsePackages" style="outline : none;text-decoration: none;color:#000;" onclick="this.getElementsByTagName('i')[0].classList.toggle('fa-caret-down');this.getElementsByTagName('i')[0].classList.toggle('fa-caret-right');"> + <i class="fa fa-caret-down" aria-hidden="true" style="margin-right:5px;cursor: pointer"></i> Packages</a> + </div> + <div class="card-body collapse show" id="collapsePackages"> + <div class="row"> + + <div class="col-sm-6"> + <div class="row"> + <div class="col-12 align-h-right mb-2" style="padding-right:0px;color:#505050;"> + <small class="text-uppercase text-muted" style="font-size: 12px;"><i class="fa fa-times-circle-o" aria-hidden="true"></i> Vulnerable:</small> + </div> + </div> + + <div id="vulnerable_package_list" class="row"> + {{ range .Glsa.Packages}} + {{ if .Affected}} + <div class="col-12"> + <div class="row"> + <div class="col-md-auto" style="color:#292929;"> + <small style="font-size: 12px;"> + <input name="package_vulnerable" value="true" hidden /> + <input name="package_atom" class="form-control" type="text" value="{{.Atom}}" style="width:150px; height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <select name="package_identifier" class="custom-select" style="display: inline-block;max-width: 100px;height: 30px;padding: .25rem .5rem;"> + <option value=">=" {{if eq .Identifier ">="}}selected{{end}}>>=</option> + <option value=">" {{if eq .Identifier ">"}}selected{{end}}>> </option> + <option value="*>=" {{if eq .Identifier "*>="}}selected{{end}}>*>= </option> + <option value="*>" {{if eq .Identifier "*>"}}selected{{end}}>*> </option> + <option value="<=" {{if eq .Identifier "<="}}selected{{end}}><= </option> + <option value="<" {{if eq .Identifier "<"}}selected{{end}}>< </option> + <option value="*<=" {{if eq .Identifier "*<="}}selected{{end}}>*<= </option> + <option value="*<" {{if eq .Identifier "*<"}}selected{{end}}>*< </option> + <option value=">=" {{if eq .Identifier "="}}selected{{end}}>= </option> + </select> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <input name="package_version" class="form-control" type="text" value="{{ .Version }}" style="width: 80px; height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <input name="package_slot" class="form-control" type="text" value="{{ .Slot }}" style="width: 30px; height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <input name="package_arch" class="form-control" type="text" value="{{ .Arch }}" style="width: 30px; height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <select name="package_auto" class="custom-select" id="inputGroupSelect01" style="display: inline-block;max-width: 100px;height: 30px;padding: .25rem .5rem;"> + <option value="yes" {{if .Auto}}selected{{end}}>yes </option> + <option value="no" {{if not .Auto}}selected{{end}}>no</option> + </select> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <button type="button" class="btn btn-outline-danger btn-delete-package" type="text" placeholder="*" style="width: 30px; height: 30px;padding: .25rem .5rem;display: inline-block">-</button> + </small> + </div> + </div> + </div> + {{end}} + {{end}} + </div> + + <div class="row mt-2"><div class="col-12"><hr/></div></div> + + + <div class="row mt-2"> + <div class="col-md-auto" style="color:#292929;"> + <small style="font-size: 12px;"> + <input id="add-vulnerable-package-atom" class="form-control" type="text" placeholder="add new package" style="width:150px;height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <select id="add-vulnerable-package-identifier" class="custom-select" id="inputGroupSelect01" style="display: inline-block;max-width: 100px;height: 30px;padding: .25rem .5rem;"> + <option value=">=" selected>>=</option> + <option value=">">> </option> + <option value="*>=">*>= </option> + <option value="*>">*> </option> + <option value="<="><= </option> + <option value="<">< </option> + <option value="*<=">*<= </option> + <option value="*<">*< </option> + <option value="=">= </option> + </select> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <input id="add-vulnerable-package-version" class="form-control" type="text" placeholder="version" style="width: 80px; height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <input id="add-vulnerable-package-slot" class="form-control" type="text" placeholder="*" style="width: 30px; height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <input id="add-vulnerable-package-arch" class="form-control" type="text" placeholder="*" style="width: 30px; height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <select id="add-vulnerable-package-auto" class="custom-select" id="inputGroupSelect01" style="display: inline-block;max-width: 100px;height: 30px;padding: .25rem .5rem;"> + <option value="true" selected>yes </option> + <option value="false">no</option> + </select> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <button type="button" class="btn btn-outline-success btn-add-vulnerable-package" type="text" placeholder="*" style="width: 30px; height: 30px;padding: .25rem .5rem;display: inline-block">+</button> + </small> + </div> + </div> + + </div> + + <div class="col-sm-6"> + + <div class="row"> + <div class="col-12 mb-2" style="padding-right:0px;color:#505050;"> + <small class="text-uppercase text-muted" style="font-size: 12px;"><i class="fa fa-shield" aria-hidden="true"></i> Unaffected:</small> + </div> + </div> + + <div id="unaffected_package_list" class="row"> + {{ range .Glsa.Packages}} + {{ if not .Affected}} + + <div class="col-12"> + <div class="row"> + <div class="col-md-auto" style="color:#292929;"> + <small style="font-size: 12px;"> + <input name="package_vulnerable" type="text" value="false" hidden /> + <input name="package_atom" class="form-control" type="text" value="{{.Atom}}" style="width:150px; height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <select name="package_identifier" class="custom-select" style="display: inline-block;max-width: 100px;height: 30px;padding: .25rem .5rem;"> + <option value=">=" {{if eq .Identifier ">="}}selected{{end}}>>=</option> + <option value=">" {{if eq .Identifier ">"}}selected{{end}}>> </option> + <option value="*>=" {{if eq .Identifier "*>="}}selected{{end}}>*>= </option> + <option value="*>" {{if eq .Identifier "*>"}}selected{{end}}>*> </option> + <option value="<=" {{if eq .Identifier "<="}}selected{{end}}><= </option> + <option value="<" {{if eq .Identifier "<"}}selected{{end}}>< </option> + <option value="*<=" {{if eq .Identifier "*<="}}selected{{end}}>*<= </option> + <option value="*<" {{if eq .Identifier "*<"}}selected{{end}}>*< </option> + <option value=">=" {{if eq .Identifier "="}}selected{{end}}>= </option> + </select> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <input name="package_version" class="form-control" type="text" value="{{.Version}}" style="width: 80px; height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <input name="package_slot" class="form-control" type="text" value="{{.Slot}}" style="width: 30px; height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <input name="package_arch" class="form-control" type="text" value="{{.Arch}}" style="width: 30px; height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <select name="package_auto" class="custom-select" id="inputGroupSelect01" style="display: inline-block;max-width: 100px;height: 30px;padding: .25rem .5rem;"> + <option value="yes" {{if .Auto}}selected{{end}}>yes </option> + <option value="no" {{if not .Auto}}selected{{end}}>no</option> + </select> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <button type="button" class="btn btn-outline-danger btn-delete-package" type="text" placeholder="*" style="width: 30px; height: 30px;padding: .25rem .5rem;display: inline-block">-</button> + </small> + </div> + </div> + </div> + + {{end}} + {{end}} + </div> + + <div class="row mt-2"><div class="col-12"><hr/></div></div> + + <div class="row mt-2"> + <div class="col-md-auto" style="color:#292929;"> + <small style="font-size: 12px;"> + <input id="add-unaffected-package-atom" class="form-control" type="text" placeholder="add new package" style="width:150px;height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <select id="add-unaffected-package-identifier" class="custom-select" style="display: inline-block;max-width: 100px;height: 30px;padding: .25rem .5rem;"> + <option value=">=" selected>>=</option> + <option value=">">> </option> + <option value="*>=">*>= </option> + <option value="*>">*> </option> + <option value="<="><= </option> + <option value="<">< </option> + <option value="*<=">*<= </option> + <option value="*<">*< </option> + <option value="=">= </option> + </select> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <input id="add-unaffected-package-version" class="form-control" type="text" placeholder="version" style="width: 80px; height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <input id="add-unaffected-package-slot" class="form-control" type="text" placeholder="*" style="width: 30px; height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <input id="add-unaffected-package-arch" class="form-control" type="text" placeholder="*" style="width: 30px; height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <select id="add-unaffected-package-auto" class="custom-select" style="display: inline-block;max-width: 100px;height: 30px;padding: .25rem .5rem;"> + <option value="1" selected>yes </option> + <option value="1">no</option> + </select> + </small> + </div> + <div class="col-md-auto pl-0" style="color:#292929;"> + <small style="font-size: 12px;"> + <button type="button" class="btn btn-outline-success btn-add-unaffected-package" type="text" placeholder="*" style="width: 30px; height: 30px;padding: .25rem .5rem;display: inline-block">+</button> + </small> + </div> + </div> + + </div> + + </div> + </div> + </div> + </div> + + + + <div class="col-6 px-0"> + + <div class="col-12 mt-4"> + <div class="card"> + <div class="card-header" style="padding-left: 8px; padding-right: 8px; padding-top: 4px; padding-bottom: 4px;font-weight:bold;font-size:13px;"> + <a data-toggle="collapse" href="#collapseBugs" style="outline : none;text-decoration: none;color:#000;" onclick="this.getElementsByTagName('i')[0].classList.toggle('fa-caret-down');this.getElementsByTagName('i')[0].classList.toggle('fa-caret-right');"> + <i class="fa fa-caret-down" aria-hidden="true" style="margin-right:5px;cursor: pointer"></i> Bugs</a> + </div> + <div class="card-body collapse show" id="collapseBugs"> + <div id="bugs-list" class="row"> + + {{ range $key, $value := .Glsa.Bugs }} + + <div class="col-sm-12 {{if ne $key 0}}mt-2{{end}}"> + <div class="row" style="margin-bottom:2px;"> + <div class="col-md-auto align-h-right" style="padding-right:0px;color:#505050;"> + <small style="font-size: 12px;"> + + <small style="font-size: 12px;"> + <input name="bugs" class="form-control" type="text" value="{{$value.Id}}" style="max-width: 75px;height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + + </small> + </div> + <div class="col py-1" style="color:#292929;padding-left:10px;"> + <small style="font-size: 12px;">{{$value.Summary}}</small> + + </div> + + <small style="font-size: 12px;margin-top: 2px;"> + <button type="button" class="btn btn-outline-danger mr-3 py-0 btn-delete-bug" type="text" style="height: 25px;display: inline-block">Delete</button> + </small> + </div> + </div> + + {{ end }} + + </div> + + <div class="row"> + <div class="col-sm-12"><hr/></div> + + <div class="col-sm-12"> + + <div class="row equal"> + <div class="col-md-auto align-h-right" style="padding-right:0px;color:#505050;"> + <small style="font-size: 12px;"> + + <small style="font-size: 12px;"> + <input class="form-control" type="text" id="new_bug_id" placeholder="bug id" style="max-width: 75px;height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + </small> + </div> + <div class="col py-1" style="color:#292929;padding-left:10px;"> + <small class="text-muted" style="font-size: 12px;">Enter a bug id to add a new bug</small> + </div> + <small style="font-size: 12px;margin-top: 2px;"> + <button type="button" class="btn btn-outline-success btn-add-bug mr-3 py-0" type="text" style="height: 25px;display: inline-block">Add</button> + </small> + </div> + </div> + + </div> + </div> + </div> + </div> + + </div> + <div class="col-6 px-0"> + + <div class="col-12 mt-4"> + <div class="card"> + <div class="card-header" style="padding-left: 8px; padding-right: 8px; padding-top: 4px; padding-bottom: 4px;font-weight:bold;font-size:13px;"> + <a data-toggle="collapse" href="#collapseReferences" style="outline : none;text-decoration: none;color:#000;" onclick="this.getElementsByTagName('i')[0].classList.toggle('fa-caret-down');this.getElementsByTagName('i')[0].classList.toggle('fa-caret-right');"> + <i class="fa fa-caret-down" aria-hidden="true" style="margin-right:5px;cursor: pointer"></i> References</a> + </div> + <div class="card-body collapse show" id="collapseReferences"> + <div id="reference_list" class="row"> + + {{ range $key, $value := .Glsa.References }} + + <div class="col-sm-12 {{if ne $key 0}}mt-2{{end}}"> + <div class="row" style="margin-bottom:2px;"> + <div class="col-md-auto align-h-right" style="padding-right:0px;color:#505050;"> + <small style="font-size: 12px;"> + + <small style="font-size: 12px;"> + <input name="reference_title" class="form-control" type="text" value="{{$value.Title}}" style="max-width: 125px;height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + + </small> + </div> + <div class="col" style="color:#292929;padding-left:10px;"> + <small style="font-size: 12px;"> + <input name="reference_url" class="form-control" type="text" value="{{$value.URL}}" style="height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + </div> + <small style="font-size: 12px;margin-top: 2px;"> + <button type="button" class="btn btn-outline-danger btn-delete-reference mr-3 py-0" type="text" style="height: 25px;display: inline-block">Delete</button> + </small> + </div> + </div> + + {{ end }} + </div> + + <div class="row"> + + <div class="col-sm-12"><hr/></div> + + <div class="col-sm-12"> + + <div class="row equal"> + <div class="col-md-auto align-h-right" style="padding-right:0px;color:#505050;"> + <small style="font-size: 12px;"> + <small style="font-size: 12px;"> + <input id="new_reference_title" class="form-control" type="text" placeholder="CVE ID" style="max-width: 125px;height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + </small> + </div> + <div class="col" style="color:#292929;padding-left:10px;"> + <small class="text-muted" style="font-size: 12px;"> + + <input id="new_reference_url" class="form-control" type="text" placeholder="Reference URL" style="height: 30px;padding: .25rem .5rem;display: inline-block" /> + </small> + + + </div> + <small style="font-size: 12px;margin-top: 2px;"> + <button type="button" class="btn btn-outline-success btn-add-reference mr-3 py-0" type="text" style="height: 25px;display: inline-block">Add</button> + </small> + </div> + </div> + + </div> + </div> + </div> + </div> + + </div> + + {{if .User.Permissions.Glsa.Comment}} + <div class="col-12 mt-3"><hr/></div> + {{else if .Glsa.Comments}} + <div class="col-12 mt-3"><hr/></div> + {{end}} + + <div class="col-12"> + <div id="comments-section" class="row"> + + {{ range .Glsa.Comments}} + + <div class="col-12 mt-3"> + <div id="c0" class="card" style="padding:0px;{{if eq .Type "approve"}}background:#DFF0D8;{{else if eq .Type "decline"}}background:#F2DEDE;{{end}}"> + <div class="card-header" style="{{if eq .Type "approve"}}background:#DFF0D8;{{else if eq .Type "decline"}}background:#F2DEDE;{{end}}"> + <div class="row"> + <div class="col-sm-8"> + <div class="row"> + <div class="col-sm-12"> + <span style="color:#000!important;"> + <span class="vcard"><a class="email" href="mailto:max@magorsch.de" title="Max Magorsch <max@magorsch.de>"> <b class="text-dark">{{.User}}</b></a></span> + </span> + <span class="ml-2"> + + <span class="badge badge-secondary" title="{{.UserBadge.Description}}" style="background: none;border: 1px solid {{.UserBadge.Color}};"> + <span class="text-capitalize" style="color: {{.UserBadge.Color}};">{{.UserBadge.Name}}</span> + </span> + </span> + </div> + <div class="col-sm-12"> + <span style="color:#505050; font-weight: normal;margin-left:2px;"> + {{.Date}} + </span> + </div> + </div> + </div> + + <div class="col-sm-4"> + <div> + <a href="#" class="btn btn-default btn-xs float-right" style="background:transparent;color:#505050;border:none;"><i class="fa fa-compress" aria-hidden="true"></i></a> + <a class="btn btn-default btn-xs float-right" href="#add_comment" style="background:transparent;color:#505050;border:none;"><i class="fa fa-reply" aria-hidden="true"></i></a> + <a href="#" class="btn btn-default btn-xs float-right" style="background:transparent;color:#505050;border:none;"><i class="fa fa-tag" aria-hidden="true"></i></a> + </div> + </div> + </div> + </div> + + <div class="card-body"> + {{if eq .Type "approve"}}<b class="mr-2">Approved: </b>{{else if eq .Type "decline"}}<b class="mr-2">Declined: </b>{{end}} + {{.Message}} + </div> + </div> + </div> + + {{end}} + + </div> + </div> + + + {{if .User.Permissions.Glsa.Comment}} + <div class="col-12 mt-4"> + <div id="add_comment"> + <label class="" for="comment" accesskey="c"><b>Add Comment</b></label> + <div class="row"> + <div class="col-12"> + <div id="comment_tabs" role="tablist"> + <div id="comment_tab" class="comment_tab active_comment_tab" role="tab" aria-selected="true">Comment</div> + <div id="comment_preview_tab" class="comment_tab" role="tab" aria-selected="false">Preview</div> + </div> + <textarea name="comment" id="comment" class="form-control comment-textarea" rows="10" cols="60" onfocusout="this.rows=10" onfocus="this.rows=15"></textarea> + <br><div class="knob-buttons"> + {{if .User.Permissions.Glsa.Approve}} + {{if eq .Glsa.CreatorId .User.Id}} + {{if .User.Permissions.Glsa.ApproveOwnGlsa}} + <input class="btn btn-outline-success btn-sm float-right mr-2" type="button" value="Approve" id="save-new-glsa-approve"> + {{end}} + {{else}} + <input class="btn btn-outline-success btn-sm float-right mr-2" type="button" value="Approve" id="save-new-glsa-approve"> + {{end}} + {{end}} + {{if .User.Permissions.Glsa.Decline}} + <input class="btn btn-outline-danger btn-sm float-right mr-2" type="button" value="Decline" id="save-new-glsa-decline"> + {{end}} + </div> + </div> + </div> + </div> + </div> + {{end}} + + + </div> + </div> + +</form> + + + +<script src="/assets/glsa.js"></script> +<script src="/assets/edit.js"></script> + + +{{template "footer" .}} + +</body> +</html> diff --git a/web/templates/glsa/show.tmpl b/web/templates/glsa/show.tmpl new file mode 100644 index 0000000..c9a9591 --- /dev/null +++ b/web/templates/glsa/show.tmpl @@ -0,0 +1,495 @@ +<!DOCTYPE html> +<html lang="en"> +{{template "head"}} +<body> +{{template "header" .}} + +<div class="container mb-5 mt-2"> + <div class="row"> + + + <div class="col-sm-12" style="margin-bottom:10px;"> + <small> + <div class="navigation"> + <a href="/all"><b>GLSA List:</b></a> + + ({{.Glsa.Id}} of {{.GlsaCount}}) + + + {{ if eq 1 .Glsa.Id }} + <span class="navigation_link"><i class="fa fa-angle-double-left" aria-hidden="true"></i> First</span> + {{else}} + <a href="/glsa/1" class="navigation_link" style="font-style: normal;"><i class="fa fa-angle-double-left" aria-hidden="true"></i> First</a> + {{end}} + + {{ if eq (prevGLSA .Glsa.Id 1) .Glsa.Id }} + <span class="navigation_link"><i class="fa fa-angle-left" aria-hidden="true"></i> Prev</span> + {{else}} + <a href="/glsa/{{prevGLSA .Glsa.Id 1}}" class="navigation_link" style="font-style: normal;"><i class="fa fa-angle-left" aria-hidden="true"></i> Prev</a> + {{end}} + + {{ if eq (nextGLSA .Glsa.Id .GlsaCount) .Glsa.Id }} + <span class="navigation_link">Next <i class="fa fa-angle-right" aria-hidden="true"></i></span> + {{else}} + <a href="/glsa/{{nextGLSA .Glsa.Id .GlsaCount}}" class="navigation_link" style="font-style: normal;">Next <i class="fa fa-angle-right" aria-hidden="true"></i></a> + {{end}} + + {{ if eq .GlsaCount .Glsa.Id }} + <span class="navigation_link" style="">Last <i class="fa fa-angle-double-right" aria-hidden="true"></i></span> + {{else}} + <a href="/glsa/{{.GlsaCount}}" class="navigation_link" style="font-style: normal;">Last <i class="fa fa-angle-double-right" aria-hidden="true"></i></a> + {{end}} + + <a href="/glsa/edit/{{.Glsa.Id}}" class="float-right btn btn-primary btn-sm">Edit GLSA</a> + + {{if .User.Permissions.Glsa.Release}} + {{if eq .Glsa.Type "draft"}} + {{if .Glsa.Status.BugReady }} + {{if eq .Glsa.Status.Approval "approved"}} + <a href="/glsa/release/{{.Glsa.Id}}" class="float-right btn btn-outline-success btn-sm" style="margin-right:5px;">Release advisory</a> + {{end}} + {{end}} + {{end}} + {{end}} + + {{if .User.Permissions.Glsa.Delete}} + <button type="button" id="btn-delete-glsa" class="float-right btn btn-outline-danger btn-sm" style="margin-right:5px;">Delete</button> + {{end}} + + <button onclick="window.scrollTo(0,document.body.scrollHeight);" class="float-right btn btn-outline-secondary btn-sm" style="margin-right:5px;">Bottom <i class="fa fa-long-arrow-down" aria-hidden="true"></i> + </button> + + + + + </div> + </small> + </div> + + <div class="col-12 mt-2"> + + + <div class="card"> + <div class="card-body"> + <div class="row"> + + <div class="col-sm-12"> + <span class="badge {{if eq .Glsa.Type "request"}}badge-danger{{else if eq .Glsa.Type "draft"}}badge-warning{{else}}badge-success{{end}} text-capitalize">{{.Glsa.Type}}</span> + <a style="color:#000000;" href="/glsa/{{.Glsa.Id}}">GLSA <span id="glsa-id">{{.Glsa.Id}}</span></a> + + <span id="summary_container"> + <small style="margin-left:5px;color:#505152;">Created: {{.Glsa.Created}}</small> + <small style="margin-left:5px;color:#505152;">Updated: {{.Glsa.Updated}}</small> + </span> + + + <span class="badge badge-secondary float-right" style="background: none;border: 1px solid {{ if eq .Glsa.Status.Permission "public"}}green{{else}}black{{end}};"> + <i class="fa {{ if eq .Glsa.Status.Permission "public"}}fa-globe{{else}}fa-user-secret{{end}} mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{ if eq .Glsa.Status.Permission "public"}}green{{else}}black{{end}};"></i> + <span style="color: {{ if eq .Glsa.Permission "public"}}green{{else}}black{{end}};">{{ if eq .Glsa.Status.Permission "public"}}PUBLIC{{else}}CONFIDENTAL{{end}}</span> + </span> + + <span class="badge badge-danger float-right mr-2" style="background: none;border: 1px solid {{if eq .Glsa.Status.WorkflowStatus "commented" }}blue{{else if eq .Glsa.Status.WorkflowStatus "own"}}green{{else if eq .Glsa.Status.WorkflowStatus "approved"}}green{{else}}darkred{{end}};"> + <i class="fa {{if eq .Glsa.Status.WorkflowStatus "commented" }}fa-comments-o{{else if eq .Glsa.Status.WorkflowStatus "own"}}fa-user{{else if eq .Glsa.Status.WorkflowStatus "approved"}}fa-check-circle-o{{else}}fa-times-circle{{end}} mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{if eq .Glsa.Status.WorkflowStatus "commented" }}blue{{else if eq .Glsa.Status.WorkflowStatus "own"}}green{{else if eq .Glsa.Status.WorkflowStatus "approved"}}green{{else}}darkred{{end}};"></i> + <span class="text-uppercase" style="color:{{if eq .Glsa.Status.WorkflowStatus "commented" }}blue{{else if eq .Glsa.Status.WorkflowStatus "own"}}green{{else if eq .Glsa.Status.WorkflowStatus "approved"}}green{{else}}darkred{{end}};">{{.Glsa.Status.WorkflowStatus}}</span> + </span> + + <span class="badge badge-secondary float-right mr-2" style="background: none;border: 1px solid {{if eq .Glsa.Status.Approval "declined" }}darkred{{else if eq .Glsa.Status.Approval "approved"}}green{{else if eq .Glsa.Status.Approval "comments"}}orange{{else}}grey{{end}};"> + <i class="fa fa-circle mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{if eq .Glsa.Status.Approval "declined" }}darkred{{else if eq .Glsa.Status.Approval "approved"}}green{{else if eq .Glsa.Status.Approval "comments"}}orange{{else}}grey{{end}};"></i> + <span class="text-uppercase" style="color:{{if eq .Glsa.Status.Approval "declined" }}darkred{{else if eq .Glsa.Status.Approval "approved"}}green{{else if eq .Glsa.Status.Approval "comments"}}orange{{else}}grey{{end}};">{{.Glsa.Status.Approval}}</span> + </span> + + <span class="badge badge-secondary float-right mr-2" style="background: none;border: 1px solid {{if .Glsa.Status.BugReady }}green{{else}}darkred{{end}};padding-top:4px!important;padding-bottom:1.6px;"> + <svg class="" style="width:13px;height:13px" viewBox="0 0 24 24"> + <path fill="{{if .Glsa.Status.BugReady }}green{{else}}darkred{{end}}" d="M20,8H17.19C16.74,7.2 16.12,6.5 15.37,6L17,4.41L15.59,3L13.42,5.17C12.96,5.06 12.5,5 12,5C11.5,5 11.05,5.06 10.59,5.17L8.41,3L7,4.41L8.62,6C7.87,6.5 7.26,7.21 6.81,8H4V10H6.09C6.03,10.33 6,10.66 6,11V12H4V14H6V15C6,15.34 6.03,15.67 6.09,16H4V18H6.81C8.47,20.87 12.14,21.84 15,20.18C15.91,19.66 16.67,18.9 17.19,18H20V16H17.91C17.97,15.67 18,15.34 18,15V14H20V12H18V11C18,10.66 17.97,10.33 17.91,10H20V8M16,15A4,4 0 0,1 12,19A4,4 0 0,1 8,15V11A4,4 0 0,1 12,7A4,4 0 0,1 16,11V15M14,10V12H10V10H14M10,14H14V16H10V14Z" /> + </svg> + <span class="" style="color:{{if .Glsa.Status.BugReady }}green{{else}}darkred{{end}};">{{if .Glsa.Status.BugReady }}READY{{else}}NOT READY{{end}}</span> + </span> + + + </div> + + <div class="col-sm-12"> + <h1 style="font-size: 20px;margin-top:10px;margin-bottom:4px;"><span id="short_desc_nonedit_display">{{.Glsa.Title}} </span></h1> + </div> + </div> + </div> + </div> + </div> + + + + <div class="col-12 mt-4"> + + <div class="card"> + <div class="card-header" style="padding-left: 8px; padding-right: 8px; padding-top: 4px; padding-bottom: 4px;font-weight:bold;font-size:13px;"> + <a data-toggle="collapse" href="#collapseMetadata" style="outline : none;text-decoration: none;color:#000;" onclick="this.getElementsByTagName('i')[0].classList.toggle('fa-caret-down');this.getElementsByTagName('i')[0].classList.toggle('fa-caret-right');"> + <i class="fa fa-caret-down" aria-hidden="true" style="margin-right:5px;cursor: pointer"></i> Metadata</a> + </div> + <div class="card-body collapse show" id="collapseMetadata"> + <div class="row"> + <div class="col-sm-3"> + <small class="mr-2 text-uppercase text-muted" style="font-size: 12px;"><i class="fa fa-unlock" aria-hidden="true"></i> Permission:</small> + <span style="">{{.Glsa.Permission}}</span> + </div> + <div class="col-sm-3"> + <small class="mr-2 text-uppercase text-muted" style="font-size: 12px;"><i class="fa fa-address-card" aria-hidden="true"></i> Access: </small> + <span style="">{{.Glsa.Access}}</span> + </div> + + <div class="col-sm-3"> + <small class="mr-2 text-uppercase text-muted" style="font-size: 12px;"><i class="fa fa-balance-scale" aria-hidden="true"></i> Severity: </small> + <span style="">{{.Glsa.Severity}}</span> + </div> + <div class="col-sm-3"> + <small class="mr-2 text-uppercase text-muted" style="font-size: 12px;"><i class="fa fa-tag" aria-hidden="true"></i> Keyword:</small> + <span style="">{{.Glsa.Keyword}}</span> + </div> + + </div> + </div> + </div> + + </div> + + + <div class="col-12 mt-4"> + <div class="card"> + <div class="card-header" style="padding-left: 8px; padding-right: 8px; padding-top: 4px; padding-bottom: 4px;font-weight:bold;font-size:13px;"> + <a data-toggle="collapse" href="#collapseOverview" style="outline : none;text-decoration: none;color:#000;" onclick="this.getElementsByTagName('i')[0].classList.toggle('fa-caret-down');this.getElementsByTagName('i')[0].classList.toggle('fa-caret-right');"> + <i class="fa fa-caret-down" aria-hidden="true" style="margin-right:5px;cursor: pointer"></i> Overview</a> + </div> + <div class="card-body collapse show" id="collapseOverview"> + <div class="row"> + + <div class="col-sm-12"> + + <div class="row" style="margin-bottom:2px;"> + <div class="col-md-auto align-h-right" style="min-width: 125px;padding-right:0px;color:#505050;"> + <small class="text-uppercase text-muted" style="font-size: 12px;"><i class="fa fa-sticky-note-o" aria-hidden="true"></i> Synopsis:</small> + </div> + <div class="col" style="color:#292929;padding-left:10px;"> + {{.Glsa.Synopsis}} + </div> + </div> + </div> + + <div class="col-sm-12"> + <div class="row mt-3" style="margin-bottom:2px;"> + <div class="col-6" style="margin-bottom:2px;"> + <div class="row"> + <div class="col-md-auto align-h-right" style="min-width: 125px; padding-right:0px;color:#505050;"> + <small class="text-uppercase text-muted" style="font-size: 12px;"><i class="fa fa-file-text-o" aria-hidden="true"></i> Description:</small> + </div> + <div class="col" style="color:#292929;padding-left:10px;"> + <span>{{.Glsa.Description}}</span> + </div> + </div> + </div> + + <div class="col-6"> + <div class="row"> + <div class="col-md-auto" style="min-width: 125px; padding-right:0px;color:#505050;"> + <small class="text-uppercase text-muted" style="font-size: 12px;"><i class="fa fa-medkit" aria-hidden="true"></i> Workaround:</small> + </div> + <div class="col" style="color:#292929;padding-left:10px;"> + <span>{{.Glsa.Workaround}}</span> + </div> + </div> + </div> + </div> + </div> + + <div class="col-12"> + <div class="row mt-3 equal"> + <div class="col-6"> + <div class="row"> + <div class="col-md-auto" style="min-width: 125px; padding-right:0px;color:#505050;"> + <small class="text-uppercase text-muted" style="font-size: 12px;"><i class="fa fa-bullseye" aria-hidden="true"></i> Impact:</small> + </div> + <div class="col" style="color:#292929;padding-left:10px;"> + <span>{{.Glsa.Impact}}</span> + </div> + </div> + </div> + + <div class="col-6"> + <div class="row" style="padding-right:0px;color:#505050;"> + <div class="col-md-auto align-h-right" style="min-width: 125px;padding-right:0px;color:#505050;"> + <small class="text-uppercase text-muted" style="font-size: 12px;"><i class="fa fa-align-right" aria-hidden="true"></i> Background:</small> + </div> + <div class="col" style="color:#292929;padding-left:10px;"> + <span>{{.Glsa.Background}}</span> + </div> + </div> + </div> + </div> + </div> + + </div> + </div> + </div> + </div> + + + + <div class="col-12 mt-4"> + <div class="card"> + <div class="card-header" style="padding-left: 8px; padding-right: 8px; padding-top: 4px; padding-bottom: 4px;font-weight:bold;font-size:13px;"> + <a data-toggle="collapse" href="#collapseResolution" style="outline : none;text-decoration: none;color:#000;" onclick="this.getElementsByTagName('i')[0].classList.toggle('fa-caret-down');this.getElementsByTagName('i')[0].classList.toggle('fa-caret-right');"> + <i class="fa fa-caret-down" aria-hidden="true" style="margin-right:5px;cursor: pointer"></i> Resolution</a> + </div> + <div class="card-body collapse show" id="collapseResolution"> + {{ if .Glsa.Resolution}} + {{ .Glsa.Resolution}} + {{else}} + <div class="w-100 text-center"><i>- no resolution yet -</i></div> + {{end}} + + </div> + </div> + </div> + + + + <div class="col-12 mt-4"> + <div class="card"> + <div class="card-header" style="padding-left: 8px; padding-right: 8px; padding-top: 4px; padding-bottom: 4px;font-weight:bold;font-size:13px;"> + <a data-toggle="collapse" href="#collapsePackages" style="outline : none;text-decoration: none;color:#000;" onclick="this.getElementsByTagName('i')[0].classList.toggle('fa-caret-down');this.getElementsByTagName('i')[0].classList.toggle('fa-caret-right');"> + <i class="fa fa-caret-down" aria-hidden="true" style="margin-right:5px;cursor: pointer"></i> Packages</a> + </div> + <div class="card-body collapse show" id="collapsePackages"> + {{ if .Glsa.Resolution}} + <div class="row"> + + <div class="col-sm-6"> + + {{ range .Glsa.Packages}} + {{ if .Affected}} + + <div class="row" style="margin-bottom:2px;"> + <div class="col-md-auto align-h-right" style="padding-right:0px;color:#505050;"> + <small class="text-uppercase text-muted" style="font-size: 12px;"><i class="fa fa-times-circle-o" aria-hidden="true"></i> Vulnerable:</small> + </div> + + <div class="col pl-3" style="color:#292929;padding-left:10px;"> + <span style="font-size: 12px;"> {{.Identifier}}{{.Atom}}-{{.Version}}:{{.Slot}} on {{.Arch}} (auto: {{.Auto}})</span> + </div> + </div> + + {{end}} + {{end}} + + </div> + + <div class="col-sm-6"> + {{ range .Glsa.Packages}} + {{ if not .Affected}} + <div class="row equal"> + <div class="col-md-auto align-h-right" style="padding-right:0px;color:#505050;"> + <small class="text-uppercase text-muted" style="font-size: 12px;"><i class="fa fa-shield" aria-hidden="true"></i> Unaffected:</small> + </div> + <div class="col pl-3" style="color:#292929;padding-left:10px;"> + <small style="font-size: 12px;"> {{.Identifier}}{{.Atom}}-{{.Version}}:{{.Slot}} on {{.Arch}} (auto: {{.Auto}}) </small> + </div> + </div> + {{end}} + {{end}} + + </div> + + </div> + {{else}} + <div class="w-100 text-center"><i>- no packages yet -</i></div> + {{end}} + </div> + </div> + </div> + + + <div class="col-6 px-0"> + + <div class="col-12 mt-4"> + <div class="card"> + <div class="card-header" style="padding-left: 8px; padding-right: 8px; padding-top: 4px; padding-bottom: 4px;font-weight:bold;font-size:13px;"> + <a data-toggle="collapse" href="#collapseBugs" style="outline : none;text-decoration: none;color:#000;" onclick="this.getElementsByTagName('i')[0].classList.toggle('fa-caret-down');this.getElementsByTagName('i')[0].classList.toggle('fa-caret-right');"> + <i class="fa fa-caret-down" aria-hidden="true" style="margin-right:5px;cursor: pointer"></i> Bugs</a> + </div> + <div class="card-body collapse show" id="collapseBugs"> + {{ if .Glsa.Bugs}} + <div class="row"> + + {{ range .Glsa.Bugs}} + + <div class="col-sm-12"> + <div class="row" style="margin-bottom:2px;"> + <div class="col-sm-2 align-h-right" style="padding-right:0px;color:#505050;"> + <small style="font-size: 12px;" title="{{if bugIsReady .}}bug is ready{{else}}bug is not ready{{end}}"> + + <svg class="mb-1" style="width:18px;height:18px" viewBox="0 0 24 24"> + <path fill="{{if bugIsReady .}}green{{else}}grey{{end}}" d="M20,8H17.19C16.74,7.2 16.12,6.5 15.37,6L17,4.41L15.59,3L13.42,5.17C12.96,5.06 12.5,5 12,5C11.5,5 11.05,5.06 10.59,5.17L8.41,3L7,4.41L8.62,6C7.87,6.5 7.26,7.21 6.81,8H4V10H6.09C6.03,10.33 6,10.66 6,11V12H4V14H6V15C6,15.34 6.03,15.67 6.09,16H4V18H6.81C8.47,20.87 12.14,21.84 15,20.18C15.91,19.66 16.67,18.9 17.19,18H20V16H17.91C17.97,15.67 18,15.34 18,15V14H20V12H18V11C18,10.66 17.97,10.33 17.91,10H20V8M16,15A4,4 0 0,1 12,19A4,4 0 0,1 8,15V11A4,4 0 0,1 12,7A4,4 0 0,1 16,11V15M14,10V12H10V10H14M10,14H14V16H10V14Z" /> + </svg> + <span style="color:{{if bugIsReady .}}green{{end}};">{{.Id}}</span>:</small> + </div> + <div class="col-sm-10" style="color:#292929;padding-left:10px;"> + <small style="font-size: 12px;">{{.Summary}}</small> + </div> + </div> + </div> + + {{end}} + + </div> + {{else}} + <div class="w-100 text-center"><i>- no bugs yet -</i></div> + {{end}} + </div> + </div> + </div> + + </div> + <div class="col-6 px-0"> + + <div class="col-12 mt-4"> + <div class="card"> + <div class="card-header" style="padding-left: 8px; padding-right: 8px; padding-top: 4px; padding-bottom: 4px;font-weight:bold;font-size:13px;"> + <a data-toggle="collapse" href="#collapseReferences" style="outline : none;text-decoration: none;color:#000;" onclick="this.getElementsByTagName('i')[0].classList.toggle('fa-caret-down');this.getElementsByTagName('i')[0].classList.toggle('fa-caret-right');"> + <i class="fa fa-caret-down" aria-hidden="true" style="margin-right:5px;cursor: pointer"></i> References</a> + </div> + <div class="card-body collapse show" id="collapseReferences"> + {{ if .Glsa.References}} + <div class="row"> + + {{ range .Glsa.References}} + + <div class="col-sm-12" style="height: 25px;"> + <div class="row"> + <div class="col-md-auto align-h-right" style="padding-right:0px;color:#505050;"> + <small style="font-size: 12px;"> + + <small style="font-size: 12px;"> + <i class="fa fa-fire" aria-hidden="true"></i> + {{.Title}} + </small> + + </small> + </div> + <div class="col" style="color:#292929;padding-left:10px;"> + <small style="font-size: 12px;"> {{.URL}} </small> + </div> + </div> + </div> + + {{end}} + + + </div> + {{else}} + <div class="w-100 text-center"><i>- no references yet -</i></div> + {{end}} + </div> + </div> + </div> + + </div> + + + {{if .User.Permissions.Glsa.Comment}} + <div class="col-12 mt-3"><hr/></div> + {{else if .Glsa.Comments}} + <div class="col-12 mt-3"><hr/></div> + {{end}} + + <div class="col-12"> + <div id="comments-section" class="row"> + + {{ range .Glsa.Comments}} + + <div class="col-12 mt-3"> + <div id="c0" class="card" style="padding:0px;{{if eq .Type "approve"}}background:#DFF0D8;{{else if eq .Type "decline"}}background:#F2DEDE;{{end}}"> + <div class="card-header" style="{{if eq .Type "approve"}}background:#DFF0D8;{{else if eq .Type "decline"}}background:#F2DEDE;{{end}}"> + <div class="row"> + <div class="col-sm-8"> + <div class="row"> + <div class="col-sm-12"> + <span style="color:#000!important;"> + <span class="vcard"><a class="email" href="mailto:max@magorsch.de" title="Max Magorsch <max@magorsch.de>"> <b class="text-dark">{{.User}}</b></a></span> + </span> + <span class="ml-2"> + + <span class="badge badge-secondary" title="{{.UserBadge.Description}}" style="background: none;border: 1px solid {{.UserBadge.Color}};"> + <span class="text-capitalize" style="color: {{.UserBadge.Color}};">{{.UserBadge.Name}}</span> + </span> + </span> + </div> + <div class="col-sm-12"> + <span style="color:#505050; font-weight: normal;margin-left:2px;"> + {{.Date}} + </span> + </div> + </div> + </div> + + <div class="col-sm-4"> + <div> + <a href="#" class="btn btn-default btn-xs float-right" style="background:transparent;color:#505050;border:none;"><i class="fa fa-compress" aria-hidden="true"></i></a> + <a class="btn btn-default btn-xs float-right" href="#add_comment" style="background:transparent;color:#505050;border:none;"><i class="fa fa-reply" aria-hidden="true"></i></a> + <a href="#" class="btn btn-default btn-xs float-right" style="background:transparent;color:#505050;border:none;"><i class="fa fa-tag" aria-hidden="true"></i></a> + </div> + </div> + </div> + </div> + + <div class="card-body"> + {{if eq .Type "approve"}}<b class="mr-2">Approved: </b>{{else if eq .Type "decline"}}<b class="mr-2">Declined: </b>{{end}} + {{.Message}} + </div> + </div> + </div> + + {{end}} + + </div> + </div> + + {{if .User.Permissions.Glsa.Comment}} + <div class="col-12 mt-4"> + <div id="add_comment"> + <label class="" for="comment" accesskey="c"><b>Add Comment</b></label> + <div class="row"> + <div class="col-12"> + <div id="comment_tabs" role="tablist"> + <div id="comment_tab" class="comment_tab active_comment_tab" role="tab" aria-selected="true">Comment</div> + <div id="comment_preview_tab" class="comment_tab" role="tab" aria-selected="false">Preview</div> + </div> + <textarea name="comment" id="comment" class="form-control comment-textarea" rows="10" cols="60" onfocusout="this.rows=10" onfocus="this.rows=15"></textarea> + <br><div class="knob-buttons"> + <input class="btn btn-outline-primary btn-sm float-right" type="button" value="Add Comment" id="save-new-glsa-comment"> + {{if .User.Permissions.Glsa.Approve}} + {{if eq .Glsa.CreatorId .User.Id}} + {{if .User.Permissions.Glsa.ApproveOwnGlsa}} + <input class="btn btn-outline-success btn-sm float-right mr-2" type="button" value="Approve" id="save-new-glsa-approve"> + {{end}} + {{else}} + <input class="btn btn-outline-success btn-sm float-right mr-2" type="button" value="Approve" id="save-new-glsa-approve"> + {{end}} + {{end}} + {{if .User.Permissions.Glsa.Decline}} + <input class="btn btn-outline-danger btn-sm float-right mr-2" type="button" value="Decline" id="save-new-glsa-decline"> + {{end}} + </div> + </div> + </div> + </div> + </div> + {{end}} + + </div> +</div> + +<script src="/assets/glsa.js"></script> + + +{{template "footer" .}} + +</body> +</html> diff --git a/web/templates/home/home.tmpl b/web/templates/home/home.tmpl new file mode 100644 index 0000000..433be8a --- /dev/null +++ b/web/templates/home/home.tmpl @@ -0,0 +1,166 @@ +<!DOCTYPE html> +<html lang="en"> +{{template "head"}} +<body> +{{template "header" .}} + +<div class="container mb-5"> + + {{ if .User.Show2FANotice }} + <div id="twofactor-notice" class="alert alert-warning pb-4" role="alert" style="background-color: #FCF8E3;"> + <i class="fa fa-times float-right" onclick="document.getElementById('twofactor-notice').style.display = 'none';" style="cursor: pointer;" aria-hidden="true"></i> + + <small><h4>You are currently <u>not</u> using any Two-Factor-Authentication.</h4> The GLSAMaker offers the ability to protect certain operations (such as the login or releasing an advisory) by using WebAuthn (e.g. Security Keys) and Time-based one-time password (e.g. Google Authenticator). + <br/> + <span class="float-right"> <a id="disable-twofactor-notice" href="#" class="mr-1">Don't show again</a> – <a class="ml-1" href="/account/2fa">2FA Settings</a></span> + </small> + </div> + {{ end }} + + + <div class="row mt-2"> + <div class="col-12"> + + + <div id="page-index"> + + <div class="jumbotron"> + <h2 class="site-welcome stick-top" style="font-family: Bitter,'Open Sans',sans-serif; font-size: 2.5em;text-align: center;margin-bottom: 1em;">Welcome to Gentoo's GLSAMaker</h2> + <div> + <form action="/search" method="get"> + + <div class="row"> + <div class="col-lg-12"> + <div class="input-group"> + <input id="large-quicksearch" name="q" class="form-control" title="Quick Search" placeholder="Enter a glsa or cve # or some search terms" autofocus="" required=""> + <div class="btn-group"> + <a href="page.cgi?id=quicksearch.html" title="Quick Search help" class="btn btn-outline-secondary" style="background: #fff;border-color:#ced4da;border-top-left-radius: 0px;border-bottom-left-radius: 0px;" type="button"><span class="fa fa-question"></span></a> + <button id="find" type="submit" class="btn btn-outline-secondary" style="background: #fff;border-color:#ced4da;" value="Quick Search">Search</button> + </div> + </div> + </div> + </div> + + </form> + + <ul class="additional_links" style="display: none;"> + </ul> + </div><br> + <small class="text-muted">The GLSAMaker supports different queries to navigate and search. Have look at the <a href="/about/search">documentation</a>.<br> + The GLSAMaker can be used either by using this website or by using the corresponding <a href="/about/cli">command line tool</a>.</small> + + </div> + </div> + + + </div> + </div> + + <!----------- page content ----------------> + + + <div class="bz_common_actions"> + + <div class="row" style="width:80%; margin: 0 auto;"> + + <div class="col-lg-3" style="cursor:pointer;"> + <a href="/new"> + <div class="row index_page_icon" style="height: 170px; width: 145px; margin: 0 auto"> + <div class="col-12"> + <i class="fa fa-file-text" aria-hidden="true" style="font-size:100px;"></i> + </div> + <div class="col-12 mt-0" style="margin-top: 15px;"> + File a Request + </div> + </div> + </a> + </div> + + <div class="col-lg-3" style="cursor:pointer;"> + <a href="/dashboard"> + <div class="row index_page_icon" style="height: 170px; width: 145px; margin: 0 auto"> + <div class="col-12"> + <i class="fa fa-tachometer" aria-hidden="true" style="font-size:100px;"></i> + </div> + <div class="col-12 mt-0" style="margin-top: 15px;"> + Dashboard + </div> + </div> + </a> + </div> + + + <div class="col-lg-3" onclick="" style="cursor:pointer;"> + <a href="/cve/tool"> + <div class="row index_page_icon" style="height: 170px; width: 145px; margin: 0 auto"> + <div class="col-12"> + <i class="fa fa-table" aria-hidden="true" style="font-size:100px;"></i> + </div> + <div class="col-12 mt-0" style="margin-top: 15px;"> + CVE Tool + </div> + </div> + </a> + </div> + + <div class="col-lg-3" style="cursor:pointer;"> + <a href="/statistics"> + <div class="row index_page_icon" style="height: 170px; width: 145px; margin: 0 auto"> + <div class="col-12"> + <i class="fa fa-bar-chart" aria-hidden="true" style="font-size:100px;"></i> + </div> + <div class="col-12 mt-0" style="margin-top: 15px;"> + Statistics + </div> + </div> + </a> + </div> + </div> + + <br><br><br><br><br> + <ul style="display: none"> + <li> + <a id="enter_bug" href="enter_bug.cgi"><span>File a Bug</span></a> + + + </li> + <li> + <a id="query" href="query.cgi"><span>Search</span></a> + </li> + <li> + <a id="account" href="userprefs.cgi"><span>User Preferences</span></a> + </li> + <li> + <a id="help" href="https://bugzilla.readthedocs.org/en/5.0/using/index.html"><span>Documentation</span></a> + </li> + </ul> + </div> + + +</div> + + +<div id="TwoFactorModal" class="modal" tabindex="-1" role="dialog"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title">Modal title</h5> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"> + <span aria-hidden="true">×</span> + </button> + </div> + <div class="modal-body"> + <p>Modal body text goes here.</p> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-primary">Save changes</button> + <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> + </div> + </div> + </div> +</div> + +{{template "footer" .}} + +</body> +</html> diff --git a/web/templates/index/show.tmpl b/web/templates/index/show.tmpl new file mode 100644 index 0000000..265ac2f --- /dev/null +++ b/web/templates/index/show.tmpl @@ -0,0 +1,85 @@ +<!DOCTYPE html> +<html lang="en"> +{{template "head"}} +<body> +{{template "header" .}} + +<style> + + .colvis-btn { + background: white !important; + border: 1px solid #ced4da; + color: #495057; + } + + .colvis-btn:hover { + background: white !important; + border: 1px solid #ced4da; + color: #495057; + } + + .dt-button-collection > .dropdown-menu { + background: #54487A; + } + + .buttons-columnVisibility:not(.active) { + background: white!important; + color: black!important; + } + + td:hover { + cursor: pointer; + } + + tr:not(.even):not(.odd), tr[role=row]:not(.even):not(.odd){ + background: none!important; + } + + .collapsing { + transition: none !important; + } + + +</style> + + +<div class="container mb-5"> + <div class="row"> + <div class="col-12"> + + <table id="table_id" class="data-table table table-striped table-hover"> + <thead> + <tr> + <th class="render-bold noVis">ID</th> + <th class="no-sort">Description</th> + <th class="hide no-sort">Packages</th> + <th class="hide no-sort render-bug">Bugs</th> + <th class="no-sort">BaseScore</th> + <th class="hide no-sort">Impact</th> + <th class="hide no-sort">References</th> + <th class="hide no-sort">Comments</th> + <th>LastModifiedDate</th> + <th class="hide">PublishedDate</th> + <th class="render-state">State</th> + <th class="hide noVis">Changelog</th> + </tr> + </thead> + </table> + + </div> + </div> +</div> + +{{template "footer" .}} + + +<script> + window.userCanComment = "{{.User.Permissions.CVETool.Comment}}" == "true"; + window.userCanChangeState = "{{.User.Permissions.CVETool.ChangeState}}" == "true"; + window.userCanAssignBug = "{{.User.Permissions.CVETool.AssignBug}}" == "true"; + window.userCanAddPackage = "{{.User.Permissions.CVETool.AddPackage}}" == "true"; +</script> + + +</body> +</html> diff --git a/web/templates/index/showFullscreen.tmpl b/web/templates/index/showFullscreen.tmpl new file mode 100644 index 0000000..e996e3f --- /dev/null +++ b/web/templates/index/showFullscreen.tmpl @@ -0,0 +1,80 @@ +<!DOCTYPE html> +<html lang="en"> +{{template "head"}} +<body style="overflow-x: hidden;border-top: none;"> + +<style> + + .colvis-btn { + background: white !important; + border: 1px solid #ced4da; + color: #495057; + } + + .colvis-btn:hover { + background: white !important; + border: 1px solid #ced4da; + color: #495057; + } + + .dt-button-collection > .dropdown-menu { + background: #54487A; + } + + .buttons-columnVisibility:not(.active) { + background: white!important; + color: black!important; + } + + td:hover { + cursor: pointer; + } + + tr:not(.even):not(.odd), tr[role=row]:not(.even):not(.odd){ + background: none!important; + } + + .collapsing { + transition: none !important; + } + + +</style> + + +<div class="container-fluid mb-5"> + <div class="row mt-3"> + <div class="col-12"> + + <table id="table_id" class="data-table table table-striped table-hover"> + <thead> + <tr> + <th class="render-bold noVis">ID</th> + <th class="no-sort">Description</th> + <th class="no-sort">Packages</th> + <th class="no-sort render-bug">Bugs</th> + <th class="no-sort">BaseScore</th> + <th class="no-sort">Impact</th> + <th class="no-sort">References</th> + <th class="hide no-sort">Comments</th> + <th class="">LastModifiedDate</th> + <th class="">PublishedDate</th> + <th class="render-state">State</th> + <th class="hide noVis">Changelog</th> + </tr> + </thead> + </table> + + </div> + </div> +</div> + +<script> + window.userCanComment = "{{.User.Permissions.CVETool.Comment}}" == "true"; + window.userCanChangeState = "{{.User.Permissions.CVETool.ChangeState}}" == "true"; + window.userCanAssignBug = "{{.User.Permissions.CVETool.AssignBug}}" == "true"; + window.userCanAddPackage = "{{.User.Permissions.CVETool.AddPackage}}" == "true"; +</script> + +</body> +</html> diff --git a/web/templates/layout/footer.tmpl b/web/templates/layout/footer.tmpl new file mode 100644 index 0000000..bdf2510 --- /dev/null +++ b/web/templates/layout/footer.tmpl @@ -0,0 +1,50 @@ +{{define "footer"}} + <footer> + <div class="container"> + <div class="row"> + <div class="col-12 offset-md-2 col-md-7"> + <h3 class="footerhead">Gentoo GLSAMaker</h3> + <div class="row"> + <div class="col-xs-12 col-md-4"> + <span class="kk-group-header">Bug Data as current of</span><br/>{{ .Application.LastBugUpdate.Format "Jan 02, 2006 15:04:05 UTC" }}<br/> + {{if .User.Permissions.Glsa.UpdateBugs}} + <a href="/glsa/bugs/update">Trigger an update</a> + {{end}} + </div> + <div class="col-xs-12 col-md-4"> + <span class="kk-group-header">CVE Data as current of</span><br/>{{ .Application.LastCVEUpdate.Format "Jan 02, 2006 15:04:05 UTC" }}<br/> + {{if .User.Permissions.CVETool.UpdateCVEs}} + <a href="/cve/update">Trigger an update</a> + {{end}} + </div> + <div class="col-xs-12 col-md-4"> + </div> + </div> + </div> + <div class="col-12 col-md-3"> + <h3 class="footerhead">Questions or comments?</h3> + Please feel free to <a href="https://www.gentoo.org/inside-gentoo/contact/">contact us</a>. + <p class="mt-2">{{ .Application.Version }}</p> + </div> + </div> + <div class="row"> + <div class="col-2 col-sm-3 col-md-2"> + <ul class="footerlinks three-icons"> + <li><a href="https://twitter.com/gentoo" title="@Gentoo on Twitter"><span class="fa fa-twitter fa-fw"></span></a></li> + <li><a href="https://www.facebook.com/gentoo.org" title="Gentoo on Facebook"><span class="fa fa-facebook fa-fw"></span></a></li> + <li><a href="https://www.reddit.com/r/Gentoo/" title="Gentoo on Reddit"><span class="fa fa-reddit-alien fa-fw"></span></a></li> + </ul> + </div> + <div class="col-10 col-sm-9 col-md-10"> + <strong>© 2001–2020 Gentoo Foundation, Inc.</strong><br> + <small> + Gentoo is a trademark of the Gentoo Foundation, Inc. + The contents of this document, unless otherwise expressly stated, are licensed under the + <a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license">CC-BY-SA-4.0</a> license. + The <a href="https://www.gentoo.org/inside-gentoo/foundation/name-logo-guidelines.html">Gentoo Name and Logo Usage Guidelines</a> apply. + </small> + </div> + </div> + </div> + </footer> +{{end}} diff --git a/web/templates/layout/head.tmpl b/web/templates/layout/head.tmpl new file mode 100644 index 0000000..e92511b --- /dev/null +++ b/web/templates/layout/head.tmpl @@ -0,0 +1,12 @@ +{{define "head"}} + <head> + <title>Gentoo GLSAMaker</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <meta name="theme-color" content="#54487a"> + <meta name="description" content="Gentoo CVE Tool"> + <script src="/assets/stylesheets.js"></script> + <script src="/assets/application.js"></script> + <link rel="icon" href="https://packages.gentoo.org/favicon.ico" type="image/x-icon"> + </head> +{{end}} diff --git a/web/templates/layout/header.tmpl b/web/templates/layout/header.tmpl new file mode 100644 index 0000000..571a58b --- /dev/null +++ b/web/templates/layout/header.tmpl @@ -0,0 +1,6 @@ +{{define "header"}} + <header> + {{template "sitetitle"}} + {{template "tyrian-navbar" .}} + </header> +{{end}} diff --git a/web/templates/layout/sitetitle.tmpl b/web/templates/layout/sitetitle.tmpl new file mode 100644 index 0000000..bce61c7 --- /dev/null +++ b/web/templates/layout/sitetitle.tmpl @@ -0,0 +1,37 @@ +{{define "sitetitle"}} + <div class="site-title"> + <div class="container"> + <div class="row justify-content-between"> + <div class="logo"> + <a href="/" title="Back to the homepage" class="site-logo"> + <img src="https://assets.gentoo.org/tyrian/site-logo.png" alt="Gentoo" srcset="https://assets.gentoo.org/tyrian/site-logo.svg"> + </a> + <span class="site-label">Security</span> + </div> + <div class="site-title-buttons"> + <div class="btn-group btn-group-sm"> + <a href="https://get.gentoo.org/" role="button" class="btn get-gentoo"><span class="fa fa-fw fa-download"></span> <strong>Get Gentoo!</strong></a> + <div class="btn-group btn-group-sm"> + <a class="btn gentoo-org-sites dropdown-toggle" data-toggle="dropdown" data-target="#" href="#"> + <span class="fa fa-fw fa-map-o"></span> <span class="d-none d-sm-inline">gentoo.org sites</span> <span class="caret"></span> + </a> + <div class="dropdown-menu dropdown-menu-right"> + <a class="dropdown-item" href="https://www.gentoo.org/" title="Main Gentoo website"><span class="fa fa-home fa-fw"></span> gentoo.org</a> + <a class="dropdown-item" href="https://wiki.gentoo.org/" title="Find and contribute documentation"><span class="fa fa-file-text-o fa-fw"></span> Wiki</a> + <a class="dropdown-item" href="https://bugs.gentoo.org/" title="Report issues and find common issues"><span class="fa fa-bug fa-fw"></span> Bugs</a> + <a class="dropdown-item" href="https://forums.gentoo.org/" title="Discuss with the community"><span class="fa fa-comments-o fa-fw"></span> Forums</a> + <a class="dropdown-item" href="https://packages.gentoo.org/" title="Find software for your Gentoo"><span class="fa fa-hdd-o fa-fw"></span> Packages</a> + <div class="dropdown-divider"></div> + <a class="dropdown-item" href="https://planet.gentoo.org/" title="Find out what's going on in the developer community"><span class="fa fa-rss fa-fw"></span> Planet</a> + <a class="dropdown-item" href="https://archives.gentoo.org/" title="Read up on past discussions"><span class="fa fa-archive fa-fw"></span> Archives</a> + <a class="dropdown-item" href="https://sources.gentoo.org/" title="Browse our source code"><span class="fa fa-code fa-fw"></span> Sources</a> + <div class="dropdown-divider"></div> + <a class="dropdown-item" href="https://infra-status.gentoo.org/" title="Get updates on the services provided by Gentoo"><span class="fa fa-server fa-fw"></span> Infra Status</a> + </div> + </div> + </div> + </div> + </div> + </div> + </div> +{{end}} diff --git a/web/templates/layout/tyriannav.tmpl b/web/templates/layout/tyriannav.tmpl new file mode 100644 index 0000000..c53f671 --- /dev/null +++ b/web/templates/layout/tyriannav.tmpl @@ -0,0 +1,72 @@ +{{define "tyrian-navbar"}} + <nav class="tyrian-navbar navbar navbar-dark navbar-expand-lg bg-primary" role="navigation"> + <div class="container"> + <div class="navbar-header"> + <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar-main-collapse" aria-controls="navbar-main-collapse" aria-expanded="false" aria-label="Toggle navigation"> + <span class="navbar-toggler-icon"></span> + </button> + </div> + <div class="collapse navbar-collapse navbar-main-collapse" id="navbar-main-collapse"> + <ul class="navbar-nav mr-auto"> + + <li class="nav-item {{ if (eq .Page "home")}}active{{end}}"><a class="nav-link" href="/">Home</a></li> + <li class="nav-item {{ if (eq .Page "new")}}active{{end}}"><a class="nav-link" href="/new">New</a></li> + <li class="nav-item {{ if (eq .Page "requests")}}active{{end}}"><a class="nav-link" href="/requests">Requests</a></li> + <li class="nav-item {{ if (eq .Page "drafts")}}active{{end}}"><a class="nav-link" href="/drafts">Drafts</a></li> + <li class="nav-item {{ if (eq .Page "cvetool")}}active{{end}}"><a class="nav-link" href="/cve/tool">CVETool</a></li> + <li class="nav-item {{ if (eq .Page "dashboard")}}active{{end}}"><a class="nav-link" href="/dashboard">Dashboard</a></li> + + <li class="nav-item dropdown"> + <a class="nav-link" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> + <i class="fa fa-angle-double-right" aria-hidden="true"></i> + </a> + <div class="dropdown-menu" aria-labelledby="navbarDropdown"> + <a class="dropdown-item" href="/archive">Archive</a> + <a class="dropdown-item" href="/all">All</a> + <a class="dropdown-item" href="/statistics">Statistics</a> + <a class="dropdown-item" href="/about">About</a> + <div class="dropdown-divider"></div> + <a class="dropdown-item" target="_blank" rel="noopener noreferrer" href="https://bugs.gentoo.org">Bugzilla <span class="fa fa-fw fa-external-link-square" style="color:#000;" title="This link will leave www.gentoo.org."></span></a> + </div> + </li> + + </ul> + + + <form class="form-inline ml-auto inlinesearch" role="search" action="/search" method="get"> + + <div id="" class="input-group"> + + <div class="input-group-prepend"> + <span class="input-group-text" id="basic-addon1"><i class="fa fa-search" aria-hidden="true"></i></span> + </div> + + <input id="quicksearch" class="form-control" type="text" name="q" type="text" placeholder="Quick Search" aria-label="Quick Search"> + </div> + + </form> + + <ul class="navbar-nav"> + {{if .User.Permissions.Admin.View}} + <li class="nav-item"><a class="nav-link" href="/admin"> + <span class="fa fa-gears" aria-hidden="true"></span> + </a> + </li> + {{end}} + <li class="nav-item dropdown"> + <a class="nav-link" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> + <span class="fa fa-user" aria-label="Personal tools"></span> + </a> + <div class="dropdown-menu" aria-labelledby="navbarDropdown"> + <a class="dropdown-item" href="/account/password">Password</a> + <a class="dropdown-item" href="/account/2fa">2FA</a> + <div class="dropdown-divider"></div> + <a class="dropdown-item" href="/logout">Logout</a> + </div> + </li> + </ul> + + </div> + </div> + </nav> +{{end}} diff --git a/web/templates/new/new.tmpl b/web/templates/new/new.tmpl new file mode 100644 index 0000000..b6ff274 --- /dev/null +++ b/web/templates/new/new.tmpl @@ -0,0 +1,282 @@ +<!DOCTYPE html> +<html lang="en"> +{{template "head"}} +<body> +{{template "header" .}} + +<div class="container mb-5"> + <div class="row"> + <div class="col-12"> + + <h2 class="ml-1 mb-4">New GLSA request </h2> + + <div class="card px-2 mx-1"> + <div class="card-body"> + + <form action="/new" method="POST"> + + + <div class="col-sm-12 pr-0"> + <span class="badge badge-danger badge-request">Request</span> + <span class="badge badge-warning badge-draft" style="display: none;">Draft</span> + <a style="color:#000000;" href="">GLSA {{.NewID}}</a> + + <span id="summary_container"> + <small style="margin-left:5px;color:#505152;">Created: 2020-04-08 16:05 UTC</small> + </span> + + + + <span class="badge badge-secondary float-right badge-public" style="background: none;border: 1px solid green;"> + <i class="fa fa-globe mr-1" aria-hidden="true" style="font-size: 0.8rem;color: green;"></i> + <span class="" style="color:green;">PUBLIC</span> + </span> + + <span class="badge badge-secondary float-right badge-confidential" style="background: none;border: 1px solid black;display: none;"> + <i class="fa fa-user-secret mr-1" aria-hidden="true" style="font-size: 0.8rem;color: black;"></i> + <span class="text-uppercase" style="color:black;">Confidential</span> + </span> + + + <span class="badge badge-danger float-right mr-2" style="background: none;border: 1px solid green;"> + <i class="fa fa-user mr-1" aria-hidden="true" style="font-size: 0.8rem;color: green;"></i> + <span class="" style="color:green;">OWN</span> + </span> + + <span class="badge badge-secondary badge-nocomment float-right mr-2" style="background: none;border: 1px solid grey;"> + <i class="fa fa-circle mr-1" aria-hidden="true" style="font-size: 0.8rem;color: grey;"></i> + <span class="" style="color:grey;">NONE</span> + </span> + + <span class="badge badge-secondary badge-comment float-right mr-2" style="background: none;border: 1px solid orange;display: none;"> + <i class="fa fa-circle mr-1" aria-hidden="true" style="font-size: 0.8rem;color: orange;"></i> + <span class="text-uppercase" style="color:orange;">Comment</span> + </span> + + + <span class="badge badge-secondary badge-notbugready float-right mr-2" style="background: none;border: 1px solid darkred;padding-top:4px!important;padding-bottom:1.6px;"> + <svg class="" style="width:13px;height:13px" viewBox="0 0 24 24"> + <path fill="darkred" d="M20,8H17.19C16.74,7.2 16.12,6.5 15.37,6L17,4.41L15.59,3L13.42,5.17C12.96,5.06 12.5,5 12,5C11.5,5 11.05,5.06 10.59,5.17L8.41,3L7,4.41L8.62,6C7.87,6.5 7.26,7.21 6.81,8H4V10H6.09C6.03,10.33 6,10.66 6,11V12H4V14H6V15C6,15.34 6.03,15.67 6.09,16H4V18H6.81C8.47,20.87 12.14,21.84 15,20.18C15.91,19.66 16.67,18.9 17.19,18H20V16H17.91C17.97,15.67 18,15.34 18,15V14H20V12H18V11C18,10.66 17.97,10.33 17.91,10H20V8M16,15A4,4 0 0,1 12,19A4,4 0 0,1 8,15V11A4,4 0 0,1 12,7A4,4 0 0,1 16,11V15M14,10V12H10V10H14M10,14H14V16H10V14Z" /> + </svg> + <span class="" style="color:darkred;">NOT READY</span> + </span> + + <span class="badge badge-secondary badge-bugready float-right mr-2" style="background: none;border: 1px solid green;padding-top:4px!important;padding-bottom:1.6px;display: none;"> + <svg class="" style="width:13px;height:13px" viewBox="0 0 24 24"> + <path fill="green" d="M20,8H17.19C16.74,7.2 16.12,6.5 15.37,6L17,4.41L15.59,3L13.42,5.17C12.96,5.06 12.5,5 12,5C11.5,5 11.05,5.06 10.59,5.17L8.41,3L7,4.41L8.62,6C7.87,6.5 7.26,7.21 6.81,8H4V10H6.09C6.03,10.33 6,10.66 6,11V12H4V14H6V15C6,15.34 6.03,15.67 6.09,16H4V18H6.81C8.47,20.87 12.14,21.84 15,20.18C15.91,19.66 16.67,18.9 17.19,18H20V16H17.91C17.97,15.67 18,15.34 18,15V14H20V12H18V11C18,10.66 17.97,10.33 17.91,10H20V8M16,15A4,4 0 0,1 12,19A4,4 0 0,1 8,15V11A4,4 0 0,1 12,7A4,4 0 0,1 16,11V15M14,10V12H10V10H14M10,14H14V16H10V14Z" /> + </svg> + <span class="" style="color:green;">READY</span> + </span> + + + </div> + + <div class="col-sm-12"> + <h1 style="font-size: 20px;margin-top:10px;margin-bottom:4px;"><span id="short_desc_nonedit_display"> + New Gentoo Linux Security Advisories Request + </span></h1> + </div> + + + <style> + .advanced-fields { + color: grey; + } + </style> + + + + <div class="row mt-5"> + <div class="col-2 text-right"> + <b>Bugs</b><br/> + <small>Please enter the relevant bug ID(s), separate more than one bug with a comma.</small> + </div> + <div class="col-10"> + <input id="bugs" name="bugs" type="text" class="form-control" style="display:inline-block;max-width: 200px;background: none;"/> + <i id="bug-spinner" class="fa fa-lg fa-refresh fa-spin ml-3" style="display: none;" aria-hidden="true"></i> + <i id="bug-refresh-ok" class="fa fa-lg fa-check ml-3" style="display: none;color: green;" aria-hidden="true"></i> + <i id="bug-refresh-failed" class="fa fa-lg fa-times ml-3" style="display: none;color: darkred;" aria-hidden="true"></i> + </div> + </div> + + <div class="row mt-4"> + <div class="col-2 text-right"> + <b>Title</b><br/> + <small>Either take the suggested title or enter a new custom one.</small> + </div> + <div class="col-10"> + <textarea id="title" name="title" rows="5" class="form-control" style="max-width: 600px;background: none;"></textarea> + </div> + </div> + + <div class="row mt-4 collapse advanced-fields" id="synopsisField"> + <div class="col-2 text-right"> + <b>Synopsis</b><br/> + <small>Either take the suggested title or enter a new custom one.</small> + </div> + <div class="col-10"> + <input id="synopsis" name="synopsis" class="form-control" style="max-width: 600px;background: none;" /> + </div> + </div> + + <div class="row mt-4 collapse advanced-fields" id="sescriptionField"> + <div class="col-2 text-right"> + <b>Description</b><br/> + <small>Either take the suggested title or enter a new custom one.</small> + </div> + <div class="col-10"> + <textarea oninput="this.value != '' ? [document.querySelector('.badge-draft').style.display = 'inline-block',document.querySelector('.badge-request').style.display = 'none'] : [document.querySelector('.badge-draft').style.display = 'none',document.querySelector('.badge-request').style.display = 'inline-block'] ; " id="description" name="description" rows="3" class="form-control" style="max-width: 600px;background: none;"></textarea> + </div> + </div> + + <div class="row mt-4 collapse advanced-fields" id="workaroundField"> + <div class="col-2 text-right"> + <b>Workaround</b><br/> + <small>Either take the suggested title or enter a new custom one.</small> + </div> + <div class="col-10"> + <textarea id="workaround" name="workaround" rows="3" class="form-control" style="max-width: 600px;background: none;"></textarea> + </div> + </div> + + <div class="row mt-4 collapse advanced-fields" id="impactField"> + <div class="col-2 text-right"> + <b>Impact</b><br/> + <small>Either take the suggested title or enter a new custom one.</small> + </div> + <div class="col-10"> + <textarea id="impact" name="impact" rows="3" class="form-control" style="max-width: 600px;background: none;"></textarea> + </div> + </div> + + <div class="row mt-4 collapse advanced-fields" id="backgroundField"> + <div class="col-2 text-right"> + <b>Background</b><br/> + <small>Either take the suggested title or enter a new custom one.</small> + </div> + <div class="col-10"> + <textarea id="background" name="background" rows="3" class="form-control" style="max-width: 600px;background: none;"></textarea> + </div> + </div> + + <div class="row mt-4 collapse advanced-fields" id="resolutionField"> + <div class="col-2 text-right"> + <b>Resolution</b><br/> + <small>Either take the suggested title or enter a new custom one.</small> + </div> + <div class="col-10"> + <textarea id="resolution" name="resolution" rows="3" class="form-control" style="max-width: 600px;background: none;"></textarea> + </div> + </div> + + + <div class="row mt-4"> + <div class="col-2 text-right"> + <b>References</b> + </div> + <div class="col-10"> + <div class="form-check"> + <input id="importReferences3" name="importReferences3" type="checkbox" class="form-check-input"> + <label class="form-check-label py-1" for="exampleCheck1"> Don't import any references</label> + </div> + <div class="form-check"> + <input id="importReferences" name="importReferences" type="checkbox" class="form-check-input"> + <label class="form-check-label py-1" for="exampleCheck1"> Import CVEs from linked bugs</label> + </div> + <div class="form-check"> + <input id="importReferences2" name="importReferences2" type="checkbox" class="form-check-input"> + <label class="form-check-label py-1" for="exampleCheck1"> Import CVEs from linked bugs and all references from the CVEs</label> + </div> + </div> + </div> + + <div class="row mt-4"> + <div class="col-2 text-right"> + <b>Permissions</b><br/> + <small>Mark this request as public or confidental.</small> + </div> + <div class="col-10"> + <select onchange="this.value == 'confidential' ? [document.querySelector('.badge-public').style.display = 'none', document.querySelector('.badge-confidential').style.display = 'block'] : [document.querySelector('.badge-public').style.display = 'block', document.querySelector('.badge-confidential').style.display = 'none']; " class="custom-select" id="permissions" name="permissions" style="max-width: 200px;" required> + <option selected value="public">public</option> + <option value="confidential">confidental</option> + </select> + </div> + </div> + + <div class="row mt-4 collapse advanced-fields" id="accessField"> + <div class="col-2 text-right"> + <b>Access</b><br/> + <small>Mark this request as public or confidental.</small> + </div> + <div class="col-10"> + <select class="custom-select" id="access" name="access" style="max-width: 200px;" required> + <option value="local">local</option> + <option selected value="remote">remote</option> + <option value="local,remote">local, remote</option> + </select> + </div> + </div> + + <div class="row mt-4 collapse advanced-fields" id="severityField"> + <div class="col-2 text-right"> + <b>Severity</b><br/> + <small>Mark this request as public or confidental.</small> + </div> + <div class="col-10"> + <select class="custom-select" id="severity" name="severity" style="max-width: 200px;" required> + <option value="low">low</option> + <option selected value="normal">normal</option> + <option value="high">high</option> + </select> + </div> + </div> + + <div class="row mt-4 collapse advanced-fields" id="keywordField"> + <div class="col-2 text-right"> + <b>Keyword</b><br/> + <small>Either take the suggested title or enter a new custom one.</small> + </div> + <div class="col-10"> + <input id="keyword" name="keyword" class="form-control" style="max-width: 300px;background: none;" /> + </div> + </div> + + <div class="row mt-4 collapse advanced-fields" id="comment"> + <div class="col-2 text-right"> + <b>Comment</b><br/> + <small>Either take the suggested title or enter a new custom one.</small> + </div> + <div class="col-10"> + <textarea oninput="this.value != '' ? [document.querySelector('.badge-comment').style.display = 'inline-block',document.querySelector('.badge-nocomment').style.display = 'none'] : [document.querySelector('.badge-comment').style.display = 'none',document.querySelector('.badge-nocomment').style.display = 'inline-block'] ; " id="comment" name="comment" rows="3" class="form-control" style="max-width: 600px;background: none;"></textarea> + </div> + </div> + + <hr class="mt-4"/> + + <div class="row mt-4"> + <div class="col-2 text-right"></div> + <div class="col-10"> + <button type="submit" class="btn btn-primary float-right"> File Request <i class="fa fa-angle-double-right ml-1" aria-hidden="true"></i></button> + <button onclick="this.innerHTML = this.innerHTML == 'Advanced Mode' ? 'Simple Mode' : 'Advanced Mode';" class="btn btn-outline-secondary float-right mr-3" type="button" data-toggle="collapse" data-target=".advanced-fields" aria-expanded="false" aria-controls="multiCollapseExample1 multiCollapseExample2">Advanced Mode</button> + + </div> + </div> + + </form> + + </div> + </div> + + + + </div> + </div> +</div> + + +{{template "footer" .}} + +<script src="/assets/newglsa.js"></script> + +</body> +</html> diff --git a/web/templates/requests/requests.tmpl b/web/templates/requests/requests.tmpl new file mode 100644 index 0000000..7a9c8a3 --- /dev/null +++ b/web/templates/requests/requests.tmpl @@ -0,0 +1,84 @@ +<!DOCTYPE html> +<html lang="en"> +{{template "head"}} +<body> +{{template "header" .}} + +<style> + td:hover { + cursor: pointer; + } +</style> + +<div class="container mb-5"> + <div class="row"> + <div class="col-12"> + + + <h1>Requests</h1> + + <table id="table_id" class="requests-data-table table table-hover"> + <thead> + <tr> + <th>ID</th> + <th>Title</th> + <th>Requester</th> + <th>Date</th> + <th>Bug Ready</th> + <th>Approved</th> + <th>Workflow</th> + <th>Permissions</th> + </tr> + </thead> + <tbody> + + {{ range .Requests}} + <tr> + <td>{{.Id}}</td> + <td>{{.Title}}</td> + <td>{{.Creator.Nick}}</td> + <td>{{.Created}}</td> + <td> + <span class="badge badge-secondary float-right mr-2" style="background: none;border: 1px solid {{if .Status.BugReady }}green{{else}}darkred{{end}};padding-top:4px!important;padding-bottom:1.6px;"> + <svg class="" style="width:13px;height:13px" viewBox="0 0 24 24"> + <path fill="{{if .Status.BugReady }}green{{else}}darkred{{end}}" d="M20,8H17.19C16.74,7.2 16.12,6.5 15.37,6L17,4.41L15.59,3L13.42,5.17C12.96,5.06 12.5,5 12,5C11.5,5 11.05,5.06 10.59,5.17L8.41,3L7,4.41L8.62,6C7.87,6.5 7.26,7.21 6.81,8H4V10H6.09C6.03,10.33 6,10.66 6,11V12H4V14H6V15C6,15.34 6.03,15.67 6.09,16H4V18H6.81C8.47,20.87 12.14,21.84 15,20.18C15.91,19.66 16.67,18.9 17.19,18H20V16H17.91C17.97,15.67 18,15.34 18,15V14H20V12H18V11C18,10.66 17.97,10.33 17.91,10H20V8M16,15A4,4 0 0,1 12,19A4,4 0 0,1 8,15V11A4,4 0 0,1 12,7A4,4 0 0,1 16,11V15M14,10V12H10V10H14M10,14H14V16H10V14Z" /> + </svg> + <span class="" style="color:{{if .Status.BugReady }}green{{else}}darkred{{end}};">{{if .Status.BugReady }}READY{{else}}NOT READY{{end}}</span> + </span> + + </td> + <td> + <span class="badge badge-secondary float-right mr-2" style="background: none;border: 1px solid {{if eq .Status.Approval "declined" }}darkred{{else if eq .Status.Approval "approved"}}green{{else if eq .Status.Approval "comments"}}orange{{else}}grey{{end}};"> + <i class="fa fa-circle mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{if eq .Status.Approval "declined" }}darkred{{else if eq .Status.Approval "approved"}}green{{else if eq .Status.Approval "comments"}}orange{{else}}grey{{end}};"></i> + <span class="text-uppercase" style="color:{{if eq .Status.Approval "declined" }}darkred{{else if eq .Status.Approval "approved"}}green{{else if eq .Status.Approval "comments"}}orange{{else}}grey{{end}};">{{.Status.Approval}}</span> + </span> + </td> + <td> + <span class="badge badge-danger float-right mr-2" style="background: none;border: 1px solid {{if eq .Status.WorkflowStatus "commented" }}blue{{else if eq .Status.WorkflowStatus "own"}}green{{else if eq .Status.WorkflowStatus "approved"}}green{{else}}darkred{{end}};"> + <i class="fa {{if eq .Status.WorkflowStatus "commented" }}fa-comments-o{{else if eq .Status.WorkflowStatus "own"}}fa-user{{else if eq .Status.WorkflowStatus "approved"}}fa-check-circle-o{{else}}fa-times-circle{{end}} mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{if eq .Status.WorkflowStatus "commented" }}blue{{else if eq .Status.WorkflowStatus "own"}}green{{else if eq .Status.WorkflowStatus "approved"}}green{{else}}darkred{{end}};"></i> + <span class="text-uppercase" style="color:{{if eq .Status.WorkflowStatus "commented" }}blue{{else if eq .Status.WorkflowStatus "own"}}green{{else if eq .Status.WorkflowStatus "approved"}}green{{else}}darkred{{end}};">{{.Status.WorkflowStatus}}</span> + </span> + </td> + <td> + <span class="badge badge-secondary float-right" style="background: none;border: 1px solid {{ if eq .Status.Permission "public"}}green{{else}}black{{end}};"> + <i class="fa {{ if eq .Status.Permission "public"}}fa-globe{{else}}fa-user-secret{{end}} mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{ if eq .Status.Permission "public"}}green{{else}}black{{end}};"></i> + <span style="color: {{ if eq .Status.Permission "public"}}green{{else}}black{{end}};">{{ if eq .Status.Permission "public"}}PUBLIC{{else}}CONFIDENTAL{{end}}</span> + </span> + </td> + </tr> + {{end}} + </tbody> + </table> + + + </div> + </div> +</div> + + + +{{template "footer" .}} + + +</body> +</html> diff --git a/web/templates/search/search.tmpl b/web/templates/search/search.tmpl new file mode 100644 index 0000000..6a71c06 --- /dev/null +++ b/web/templates/search/search.tmpl @@ -0,0 +1,84 @@ +<!DOCTYPE html> +<html lang="en"> +{{template "head"}} +<body> +{{template "header" .}} + +<style> + td:hover { + cursor: pointer; + } +</style> + +<div class="container mb-5"> + <div class="row"> + <div class="col-12"> + + + <h1>Search Results for: "{{.SearchQuery}}"</h1> + + <table id="table_id" class="requests-data-table table table-hover"> + <thead> + <tr> + <th>ID</th> + <th>Title</th> + <th>Requester</th> + <th>Date</th> + <th>Bug Ready</th> + <th>Approved</th> + <th>Workflow</th> + <th>Permissions</th> + </tr> + </thead> + <tbody> + + {{ range .GLSAs}} + <tr> + <td>{{.Id}}</td> + <td>{{.Title}}</td> + <td>{{.Creator.Nick}}</td> + <td>{{.Created}}</td> + <td> + <span class="badge badge-secondary float-right mr-2" style="background: none;border: 1px solid {{if .Status.BugReady }}green{{else}}darkred{{end}};padding-top:4px!important;padding-bottom:1.6px;"> + <svg class="" style="width:13px;height:13px" viewBox="0 0 24 24"> + <path fill="{{if .Status.BugReady }}green{{else}}darkred{{end}}" d="M20,8H17.19C16.74,7.2 16.12,6.5 15.37,6L17,4.41L15.59,3L13.42,5.17C12.96,5.06 12.5,5 12,5C11.5,5 11.05,5.06 10.59,5.17L8.41,3L7,4.41L8.62,6C7.87,6.5 7.26,7.21 6.81,8H4V10H6.09C6.03,10.33 6,10.66 6,11V12H4V14H6V15C6,15.34 6.03,15.67 6.09,16H4V18H6.81C8.47,20.87 12.14,21.84 15,20.18C15.91,19.66 16.67,18.9 17.19,18H20V16H17.91C17.97,15.67 18,15.34 18,15V14H20V12H18V11C18,10.66 17.97,10.33 17.91,10H20V8M16,15A4,4 0 0,1 12,19A4,4 0 0,1 8,15V11A4,4 0 0,1 12,7A4,4 0 0,1 16,11V15M14,10V12H10V10H14M10,14H14V16H10V14Z" /> + </svg> + <span class="" style="color:{{if .Status.BugReady }}green{{else}}darkred{{end}};">{{if .Status.BugReady }}READY{{else}}NOT READY{{end}}</span> + </span> + + </td> + <td> + <span class="badge badge-secondary float-right mr-2" style="background: none;border: 1px solid {{if eq .Status.Approval "declined" }}darkred{{else if eq .Status.Approval "approved"}}green{{else if eq .Status.Approval "comments"}}orange{{else}}grey{{end}};"> + <i class="fa fa-circle mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{if eq .Status.Approval "declined" }}darkred{{else if eq .Status.Approval "approved"}}green{{else if eq .Status.Approval "comments"}}orange{{else}}grey{{end}};"></i> + <span class="text-uppercase" style="color:{{if eq .Status.Approval "declined" }}darkred{{else if eq .Status.Approval "approved"}}green{{else if eq .Status.Approval "comments"}}orange{{else}}grey{{end}};">{{.Status.Approval}}</span> + </span> + </td> + <td> + <span class="badge badge-danger float-right mr-2" style="background: none;border: 1px solid {{if eq .Status.WorkflowStatus "commented" }}blue{{else if eq .Status.WorkflowStatus "own"}}green{{else if eq .Status.WorkflowStatus "approved"}}green{{else}}darkred{{end}};"> + <i class="fa {{if eq .Status.WorkflowStatus "commented" }}fa-comments-o{{else if eq .Status.WorkflowStatus "own"}}fa-user{{else if eq .Status.WorkflowStatus "approved"}}fa-check-circle-o{{else}}fa-times-circle{{end}} mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{if eq .Status.WorkflowStatus "commented" }}blue{{else if eq .Status.WorkflowStatus "own"}}green{{else if eq .Status.WorkflowStatus "approved"}}green{{else}}darkred{{end}};"></i> + <span class="text-uppercase" style="color:{{if eq .Status.WorkflowStatus "commented" }}blue{{else if eq .Status.WorkflowStatus "own"}}green{{else if eq .Status.WorkflowStatus "approved"}}green{{else}}darkred{{end}};">{{.Status.WorkflowStatus}}</span> + </span> + </td> + <td> + <span class="badge badge-secondary float-right" style="background: none;border: 1px solid {{ if eq .Status.Permission "public"}}green{{else}}black{{end}};"> + <i class="fa {{ if eq .Status.Permission "public"}}fa-globe{{else}}fa-user-secret{{end}} mr-1" aria-hidden="true" style="font-size: 0.8rem;color: {{ if eq .Status.Permission "public"}}green{{else}}black{{end}};"></i> + <span style="color: {{ if eq .Status.Permission "public"}}green{{else}}black{{end}};">{{ if eq .Status.Permission "public"}}PUBLIC{{else}}CONFIDENTAL{{end}}</span> + </span> + </td> + </tr> + {{end}} + </tbody> + </table> + + + </div> + </div> +</div> + + + +{{template "footer" .}} + + +</body> +</html> diff --git a/web/templates/statistics/statistics.tmpl b/web/templates/statistics/statistics.tmpl new file mode 100644 index 0000000..134e7e0 --- /dev/null +++ b/web/templates/statistics/statistics.tmpl @@ -0,0 +1,89 @@ +<!DOCTYPE html> +<html lang="en"> +{{template "head"}} +<body> +{{template "header" .}} + +<div class="container mb-5"> + + + <h1 class="mb-4"> + Statistics<br/> + <small class="text-muted" style="font-size: 70%;">Stay tuned, this is just a first placeholder. More is coming soon.</small> + </h1> + + + <style> + #bar > svg{ + display:block; + } + #bar{ + width:100%; + height:400px; + margin:0; + padding: 0; + } + </style> + + <div class="col-12"> + + <div id="bar"></div> + + </div> + + + +</div> + + +{{template "footer" .}} + +<script> + window.CHART_DATA = [ + { + type: 'GLSAs', + stage: 'request', + count: {{.Data.Requests}}, + }, + { + type: 'GLSAs', + stage: 'draft', + count: {{.Data.Drafts}}, + }, + { + type: 'GLSAs', + stage: 'glsa', + count: {{.Data.Glsas}}, + }, + { + type: 'CVEs', + stage: 'New', + count: {{.Data.New}}, + }, + { + type: 'CVEs', + stage: 'Assigned', + count: {{.Data.Assigned}}, + }, + { + type: 'CVEs', + stage: 'Later', + count: {{.Data.Later}}, + }, + { + type: 'CVEs', + stage: 'NFU', + count: {{.Data.NFU}}, + }, + { + type: 'CVEs', + stage: 'Invalid', + count: {{.Data.Invalid}}, + } + ]; +</script> + +<script src="/assets/statistics.js"></script> + +</body> +</html> |