changeset 45:7c4d001839e7

Move the Display of the ProductTree to its own page
author Benoît Allard <benoit.allard@greenbone.net>
date Tue, 07 Oct 2014 13:01:10 +0200
parents df5182d0787f
children 086e35c4aee7
files farol/producttree.py farol/templates/document/view.j2 farol/templates/producttree/edit_branch.j2 farol/templates/producttree/edit_group.j2 farol/templates/producttree/edit_product.j2 farol/templates/producttree/edit_relationship.j2 farol/templates/producttree/view.j2
diffstat 7 files changed, 122 insertions(+), 64 deletions(-) [+]
line wrap: on
line diff
--- a/farol/producttree.py	Tue Oct 07 09:45:46 2014 +0200
+++ b/farol/producttree.py	Tue Oct 07 13:01:10 2014 +0200
@@ -49,8 +49,14 @@
 @document_required
 def create():
     get_current().createProductTree()
-    return redirect(url_for('document.view'))
+    return redirect(url_for('.view'))
 
+@producttree.route('/')
+@document_required
+@producttree_required
+def view():
+    return render_template('producttree/view.j2',
+                           producttree=get_current()._producttree)
 
 @producttree.route('/branch/<path:path>/edit', methods=['GET', 'POST'])
 @document_required
@@ -82,7 +88,7 @@
 
     branch._type = request.form['type']
     branch._name = request.form['name']
-    return redirect(url_for('document.view'))
+    return redirect(url_for('.view'))
 
 @producttree.route('/branch/add', methods=['GET', 'POST'])
 @document_required
@@ -99,7 +105,7 @@
         pbranch = ptree.getBranch([int(p) for p in request.form['parent'].split('/')])
     branch = CVRFProductBranch(request.form['type'], request.form['name'], pbranch)
     ptree.addBranch(branch)
-    return redirect(url_for('document.view'))
+    return redirect(url_for('.view'))
 
 @producttree.route('/product/<productid>')
 @document_required
@@ -158,7 +164,7 @@
     product._productid = request.form['productid']
     product._name = request.form['name']
     product._cpe = request.form['cpe'] or None
-    return redirect(url_for('document.view'))
+    return redirect(url_for('.view'))
 
 @producttree.route('/product/add', methods=['GET', 'POST'])
 @document_required
@@ -185,7 +191,7 @@
 
     product = CVRFFullProductName(request.form['productid'], request.form['name'], parent, request.form['cpe'] or None)
     ptree.addProduct(product)
-    return redirect(url_for('document.view'))
+    return redirect(url_for('.view'))
 
 @producttree.route('/relationship/<int:index>/edit', methods=['GET', 'POST'])
 @document_required
@@ -204,7 +210,7 @@
     rel._productreference = request.form['productreference']
     rel._relationtype = request.form['relationtype']
     rel._relatestoproductreference = request.form['relatestoproductreference']
-    return redirect(url_for('document.view'))
+    return redirect(url_for('.view'))
 
 @producttree.route('/relationship/add', methods=['GET', 'POST'])
 @document_required
@@ -228,7 +234,7 @@
 
     rel = CVRFRelationship(prodid1, request.form['relationtype'], prodid2)
     ptree.addRelationship(rel)
-    return redirect(url_for('document.view'))
+    return redirect(url_for('.view'))
 
 @producttree.route('/group/<groupid>/edit', methods=['GET', 'POST'])
 @document_required
@@ -246,7 +252,7 @@
     group._productids = []
     for productid in request.form.getlist('products'):
         group.addProductID(productid)
-    return redirect(url_for('document.view'))
+    return redirect(url_for('.view'))
 
 @producttree.route('/group/add', methods=['GET', 'POST'])
 @document_required
@@ -260,4 +266,4 @@
     for productid in request.form.getlist('products'):
         group.addProductID(productid)
     get_current()._producttree.addGroup(group)
-    return redirect(url_for('document.view'))
+    return redirect(url_for('.view'))
--- a/farol/templates/document/view.j2	Tue Oct 07 09:45:46 2014 +0200
+++ b/farol/templates/document/view.j2	Tue Oct 07 13:01:10 2014 +0200
@@ -136,58 +136,10 @@
 
 <div class="clearfix">
   <div class="col-md-6">
-    {% call panel(type="danger", heading="Product Tree", title=3) %}
+    {% call panel(type="danger", heading="Product Tree", title=3, collapsible=False) %}
       {% if cvrf._producttree %}
-        {% call panel(heading="Branches", badge=cvrf._producttree._branches | length, title=4, extended=True) %}
-          {% for branch in cvrf._producttree._branches recursive %}
-            {% call panel() %}
-              <p>{{ branch._type}}: <em>{{ branch._name }}</em> (<a href="{{ url_for('producttree.edit_branch', path=branch.getPath() | join('/')) }}">edit</a>)</p>
-              {% if branch._product %}
-                <strong><a href="{{ url_for('producttree.view_product', productid=branch._product._productid) }}">{{ branch._product._name }}</a></strong> (<a href="{{ url_for('producttree.edit_product', productid=branch._product._productid) }}">edit</a>)
-              {% else %}
-                {{ loop(branch._childs) }}
-              {% endif %}
-              {% if branch.isOrphaned() %}
-                <p class="text-danger">This branch is <em>orphaned</em>. A <a href="{{ url_for('producttree.add_product') }}">product</a> or a new <a href="{{ url_for('producttree.add_branch') }}">branch</a> should be created as child of this one.</p>
-              {% endif %}
-            {% endcall %}
-          {% endfor %}
-          <a href="{{ url_for('producttree.add_branch') }}" class="pull-right">add branch</a>
-        {% endcall %}
-        {% call panel(heading="Products", badge=cvrf._producttree.nbProducts(), title=4) %}
-          {% for product in cvrf._producttree._products if product._parent is sameas cvrf._producttree %}
-            <p><strong><a href="{{ url_for('producttree.view_product', productid=product._productid) }}">{{ product._name }}</a></strong> (<a href="{{ url_for('producttree.edit_product', productid=product._productid) }}">edit</a>)</p>
-          {% endfor %}
-          <a href="{{ url_for('producttree.add_product') }}" class="pull-right">add product</a>
-        {% endcall %}
-        {% call panel(heading="Relationships", badge=cvrf._producttree._relationships | length, title=4) %}
-          {% for relationship in cvrf._producttree._relationships %}
-            {% call panel() %}
-              <p><em>{{ cvrf.getProductForID(relationship._productreference)._name }}</em> as {{ relationship._relationtype | lower }} <em>{{ cvrf.getProductForID(relationship._relatestoproductreference)._name }}</em> (<a href="{{ url_for('producttree.edit_relationship', index=loop.index0) }}">edit</a>)</p>
-              {% if relationship._product %}<p><strong><a href="{{ url_for('producttree.view_product', productid=relationship._product._productid) }}">{{ relationship._product._name }}</a></strong> (<a href="{{ url_for('producttree.edit_product', productid=relationship._product._productid) }}">edit</a>)</p>{% endif %}
-              {% if relationship.isOrphaned() %}
-                <p class="text-danger">This relationship is <em>orphaned</em>. A product should be <a href="{{ url_for('producttree.add_product') }}">created</a> as child of this one.</p>
-              {% endif %}
-            {% endcall %}
-          {% endfor %}
-          <a href="{{ url_for('producttree.add_relationship') }}" class="pull-right">add</a>
-        {% endcall %}
-        {% call panel(heading="Groups", badge=cvrf._producttree._groups | length, title=4) %}
-          {% for group in cvrf._producttree._groups %}
-            {% call panel() %}
-              <a href="{{ url_for('producttree.edit_group', groupid=group._groupid) }}" class="pull-right">edit</a>
-              <ul>
-                {% for productid in group._productids %}
-                  {% with product = cvrf.getProductForID(productid) %}
-                    <li><a href="{{ url_for('producttree.view_product', productid=product._productid) }}">{{ product._name }}</a></li>
-                  {% endwith %}
-                {% endfor %}
-              </ul>
-              {% if group._description %}<p class="small">{{ group._description }}</p>{% endif %}
-            {% endcall %}
-          {% endfor %}
-          <a href="{{ url_for('producttree.add_group') }}" class="pull-right">add</a>
-        {% endcall %}
+        <p>{{ cvrf._producttree._products | length }} Products defined</p>
+        <a href="{{ url_for('producttree.view') }}">View</a>
       {% else %}
         <em>No Product tree present</em>
         <form action="{{ url_for('producttree.create') }}" method="POST" name="createProdTree">
--- a/farol/templates/producttree/edit_branch.j2	Tue Oct 07 09:45:46 2014 +0200
+++ b/farol/templates/producttree/edit_branch.j2	Tue Oct 07 13:01:10 2014 +0200
@@ -35,6 +35,6 @@
 {{ selectinput2('parent', "Path to Parent Branch", branches, branch.getParentPath()) }}
 
 <button class="btn btn-primary" type="submit">{{ action or 'Update' }}</button>
-<a class="btn btn-danger" href="{{ url_for('document.view') }}">Cancel</a>
+<a class="btn btn-danger" href="{{ url_for('.view') }}">Cancel</a>
 </form>
 {% endblock %}
--- a/farol/templates/producttree/edit_group.j2	Tue Oct 07 09:45:46 2014 +0200
+++ b/farol/templates/producttree/edit_group.j2	Tue Oct 07 13:01:10 2014 +0200
@@ -35,6 +35,6 @@
 {{ selectinput2('products', "Products", products, productids, multiple=True) }}
 
 <button class="btn btn-primary" type="submit">{{ action or 'Update' }}</button>
-<a class="btn btn-danger" href="{{ url_for('document.view') }}">Cancel</a>
+<a class="btn btn-danger" href="{{ url_for('.view') }}">Cancel</a>
 </form>
 {% endblock %}
--- a/farol/templates/producttree/edit_product.j2	Tue Oct 07 09:45:46 2014 +0200
+++ b/farol/templates/producttree/edit_product.j2	Tue Oct 07 13:01:10 2014 +0200
@@ -40,6 +40,6 @@
 {{ selectinput2('parent_relationship', "Parent relationship", orphaned_relationships, current_rel) }}
 
 <button class="btn btn-primary" type="submit">{{ action }}</button>
-<a class="btn btn-danger" href="{{ url_for('document.view') }}">Cancel</a>
+<a class="btn btn-danger" href="{{ url_for('.view') }}">Cancel</a>
 </form>
 {% endblock %}
--- a/farol/templates/producttree/edit_relationship.j2	Tue Oct 07 09:45:46 2014 +0200
+++ b/farol/templates/producttree/edit_relationship.j2	Tue Oct 07 13:01:10 2014 +0200
@@ -35,6 +35,6 @@
 {{ selectinput2('relatestoproductreference', "Relates to Product Reference", products, relatestoproductreference) }}
 
 <button class="btn btn-primary" type="submit">{{ action or 'Update' }}</button>
-<a class="btn btn-danger" href="{{ url_for('document.view') }}">Cancel</a>
+<a class="btn btn-danger" href="{{ url_for('.view') }}">Cancel</a>
 </form>
 {% endblock %}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/farol/templates/producttree/view.j2	Tue Oct 07 13:01:10 2014 +0200
@@ -0,0 +1,100 @@
+{#
+# Description:
+# Web Template used in Farol Design
+#
+# Authors:
+# BenoƮt Allard <benoit.allard@greenbone.net>
+#
+# Copyright:
+# Copyright (C) 2014 Greenbone Networks GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+-#}
+
+{% extends "base.j2" %}
+{% from "macros.j2" import panel, modal %}
+{% block title %}Product Tree{% endblock %}
+
+{% set active = 'product' %}
+
+{% block content %}
+<div class='page-header'>
+  <h1>Document's Product Tree<a href="#prodtree_modal" data-toggle="modal">?</a> <small>{{ producttree._products | length }} Products defined</small></h1>
+</div>
+{% call modal('prodtree_modal', "Product Tree") %}
+<p>The <strong>Product Tree</strong> container contains all the fully qualified product names that can be referenced elsewhere in the document (specifically when describing the products that are affected by a vulnerability using the <strong>Product Statuses</strong>, <strong>Threats</strong>, <strong>CVSS Score Sets</strong>, and <strong>Remediation</strong> containers). The <strong>Product Tree</strong> can have as many branches as needed, but each endpoint of the tree must be terminated with a <strong>Full Product Name</strong> element, which represents a product that can be referenced elsewhere.</p>
+<p>The <strong>Product Tree</strong> can be kept simple (flat) or made more detailed (branched out). It also supports concatenating products to describe relationships, such as components contained in a product or products installed on other products.</p>
+<dl>
+  <dt>Flat:</dt>
+  <dd><p>In the simplest case, a flat <strong>Product TreeM</strong> would contain one or more <strong>Full Product Name</strong> elements at the root level, one for each product that needs to be described.</p></dd>
+  <dt>Branched:</dt>
+  <dd><p>In a more detailed <strong>Product Tree</strong>, the root element would contain one or more <strong>Branch</strong> elements at the root level, one for each class/type/category of product, each of which again contains one or more <strong>Branch</strong> elements until all desired categories and subcategories are described to the satisfaction of the document issuer. Then each open <strong>Branch</strong> element is terminated with the actual product item in the form of a <strong>Full Product Name</strong> element.</p></dd>
+  <dt>Concatenated:</dt>
+  <dd><p>No matter whether a flat or branched structure is chosen, you may need to be able to describe the combination of two <strong>Full Product Name</strong> elements, such as when a product is only vulnerable when installed together with another, or to describe operating system components. To do that, a <strong>Relationship</strong> element is inserted at the root of the <strong>Product Tree</strong>, with attributes establishing a link between two existing <strong>Full Product Name</strong> elements, allowing the document producer to define a combination of two products that form a new <strong>Full Product Name</strong> entry.</p></dd>
+  <dt>Grouped:</dt>
+  <dd><p>Once <strong>Full Product Name</strong> elements are defined, they may be freely added to logical groups, which may then be used to refer to a group of products. Given that it is possible for a product to be a member of more than one logical group, some areas of the CVRF document may not allow references to product groups to avoid ambiguity.</p></dd>
+</dl>
+{% endcall %}
+{% call panel(heading="Branches", badge=producttree._branches | length, title=4, extended=True) %}
+  {% for branch in producttree._branches recursive %}
+    {% call panel() %}
+      <p>{{ branch._type}}: <em>{{ branch._name }}</em> (<a href="{{ url_for('producttree.edit_branch', path=branch.getPath() | join('/')) }}">edit</a>)</p>
+      {% if branch._product %}
+        <strong><a href="{{ url_for('producttree.view_product', productid=branch._product._productid) }}">{{ branch._product._name }}</a></strong> (<a href="{{ url_for('producttree.edit_product', productid=branch._product._productid) }}">edit</a>)
+      {% else %}
+        {{ loop(branch._childs) }}
+      {% endif %}
+      {% if branch.isOrphaned() %}
+        <p class="text-danger">This branch is <em>orphaned</em>. A <a href="{{ url_for('producttree.add_product') }}">product</a> or a new <a href="{{ url_for('producttree.add_branch') }}">branch</a> should be created as child of this one.</p>
+      {% endif %}
+    {% endcall %}
+  {% endfor %}
+  <a href="{{ url_for('producttree.add_branch') }}" class="pull-right">add branch</a>
+{% endcall %}
+{% call panel(heading="Products", badge=producttree.nbProducts(), title=4) %}
+  {% for product in producttree._products if product._parent is sameas producttree %}
+    <p><strong><a href="{{ url_for('producttree.view_product', productid=product._productid) }}">{{ product._name }}</a></strong> (<a href="{{ url_for('producttree.edit_product', productid=product._productid) }}">edit</a>)</p>
+  {% endfor %}
+  <a href="{{ url_for('producttree.add_product') }}" class="pull-right">add product</a>
+{% endcall %}
+{% call panel(heading="Relationships", badge=producttree._relationships | length, title=4) %}
+  {% for relationship in producttree._relationships %}
+    {% call panel() %}
+      <p><em>{{ cvrf.getProductForID(relationship._productreference)._name }}</em> as {{ relationship._relationtype | lower }} <em>{{ cvrf.getProductForID(relationship._relatestoproductreference)._name }}</em> (<a href="{{ url_for('producttree.edit_relationship', index=loop.index0) }}">edit</a>)</p>
+      {% if relationship._product %}<p><strong><a href="{{ url_for('producttree.view_product', productid=relationship._product._productid) }}">{{ relationship._product._name }}</a></strong> (<a href="{{ url_for('producttree.edit_product', productid=relationship._product._productid) }}">edit</a>)</p>{% endif %}
+      {% if relationship.isOrphaned() %}
+        <p class="text-danger">This relationship is <em>orphaned</em>. A product should be <a href="{{ url_for('producttree.add_product') }}">created</a> as child of this one.</p>
+      {% endif %}
+    {% endcall %}
+  {% endfor %}
+  <a href="{{ url_for('producttree.add_relationship') }}" class="pull-right">add</a>
+{% endcall %}
+{% call panel(heading="Groups", badge=producttree._groups | length, title=4) %}
+  {% for group in producttree._groups %}
+    {% call panel() %}
+      <a href="{{ url_for('producttree.edit_group', groupid=group._groupid) }}" class="pull-right">edit</a>
+      <ul>
+        {% for productid in group._productids %}
+          {% with product = cvrf.getProductForID(productid) %}
+            <li><a href="{{ url_for('producttree.view_product', productid=product._productid) }}">{{ product._name }}</a></li>
+          {% endwith %}
+        {% endfor %}
+      </ul>
+      {% if group._description %}<p class="small">{{ group._description }}</p>{% endif %}
+    {% endcall %}
+  {% endfor %}
+  <a href="{{ url_for('producttree.add_group') }}" class="pull-right">add</a>
+{% endcall %}
+{% endblock %}

http://farol.wald.intevation.org