diff farol/main.py @ 0:4a9f23230eba

Initial Release
author Benoît Allard <benoit.allard@greenbone.net>
date Wed, 24 Sep 2014 10:07:49 +0200
parents
children 63b00c10ada8
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/farol/main.py	Wed Sep 24 10:07:49 2014 +0200
@@ -0,0 +1,380 @@
+# -*- encoding: utf-8 -*-
+# Description:
+# Farol Web Application
+#
+# 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.
+
+import os
+
+from farolluz.cvrf import (CVRF, CVRFPublisher, CVRFTracking, CVRFTrackingID,
+    CVRFGenerator, CVRFRevision, CVRFReference, CVRFAcknowledgment, CVRFNote,
+    ValidationError, CVRFAggregateSeverity)
+from farolluz.parsers.cvrf import parse, parseVersion, parseDate
+from farolluz.py2 import urlopen
+from farolluz.renderer import render as render_cvrf
+from farolluz.utils import utcnow
+
+from flask import Flask, request, render_template, redirect, url_for, flash, abort
+from werkzeug import secure_filename
+
+from .session import get_current, set_current, has_current, del_current, document_required
+from .vulnerability import vulnerability
+from .producttree import producttree
+
+app = Flask(__name__)
+
+app.register_blueprint(vulnerability, url_prefix='/vulnerability')
+app.register_blueprint(producttree, url_prefix='/producttree')
+
+@app.context_processor
+def cache_content():
+    """ List the documents in cache """
+    if 'CACHE_DIRECTORY' not in app.config:
+        return dict(cache=[])
+    dirname = app.config['CACHE_DIRECTORY']
+    if not os.path.exists(dirname):
+        os.mkdir(dirname)
+    l = []
+    for path in os.listdir(dirname):
+        name, ext = os.path.splitext(path)
+        if ext == '.xml':
+            l.append(name)
+    return dict(cache=l)
+
+@app.context_processor
+def doc_properties():
+    if not has_current():
+        return {'has_current': False}
+    cvrf = get_current()
+    vulns = [(v.getTitle(), v._ordinal) for v in cvrf._vulnerabilities]
+    prods = []
+    if cvrf._producttree:
+        prods = [(p._name, p._productid) for p in cvrf._producttree._products]
+    try:
+        cvrf.validate()
+        error = None
+    except ValidationError as ve:
+        error = ve
+    return dict(has_current=True, vulnerabilities=vulns, products=prods, error=error)
+
+@app.template_filter('secure_filename')
+def makeId(string):
+    return secure_filename(string)
+
+@app.route('/new', methods=['GET', 'POST'])
+def new():
+    if request.method != 'POST':
+        return render_template('new.j2', has_document=has_current(), now=utcnow())
+
+    if 'url' in request.form:
+        set_current(parse(urlopen(request.form['url']).read()))
+    elif 'local' in request.files:
+        upload = request.files['local']
+        if not upload.filename.endswith('.xml'):
+            flash('Uploaded files should end in .xml', 'danger')
+            return redirect(url_for('new'))
+        fpath = os.path.join('/tmp', secure_filename(upload.filename))
+        upload.save(fpath)
+        with open(fpath, 'rt') as f:
+            set_current(parse(f))
+        os.remove(fpath)
+    elif 'text' in request.form:
+        set_current(parse(request.form['text'].encode('utf-8')))
+    else:
+        set_current(CVRF(request.form['title'], request.form['type']))
+    return redirect(url_for('document'))
+
+@app.route('/')
+@document_required
+def document():
+    cvrf = get_current()
+    return render_template('doc.j2', cvrf=cvrf)
+
+@app.route('/title/edit', methods=['GET', 'POST'])
+@document_required
+def edit_title():
+    if request.method != 'POST':
+        return render_template('edit_title.j2', title = get_current()._title, _type = get_current()._type)
+
+
+    get_current()._title = request.form['title']
+    get_current()._type = request.form['type']
+    return redirect(url_for('document'))
+
+@app.route('/publisher/edit', methods=['GET', 'POST'])
+@document_required
+def edit_publisher():
+    if request.method != 'POST':
+        return render_template('edit_publisher.j2', publisher = get_current()._publisher or CVRFPublisher(''), types=CVRFPublisher.TYPES)
+
+    publisher = CVRFPublisher(request.form['type'], request.form['vendorid'] or None)
+    publisher.setContact(request.form['contact'] or None)
+    publisher.setAuthority(request.form['authority'] or None)
+    get_current().setPublisher(publisher)
+    return redirect(url_for('document'))
+
+@app.route('/tracking/edit', methods=['GET', 'POST'])
+@document_required
+def edit_tracking():
+    wasNone = False
+    tracking = get_current()._tracking
+    if tracking is None:
+        wasNone = True
+        tracking = CVRFTracking(CVRFTrackingID(''), 'Draft', (0,), utcnow(), utcnow())
+    generator = tracking._generator
+    if not tracking._generator:
+        generator = CVRFGenerator()
+    if request.method != 'POST':
+        return render_template('edit_tracking.j2', tracking=tracking, version='.'.join('%s'%v for v in tracking._version), generator=generator, now=utcnow(), statuses=tracking.STATUSES)
+
+    tracking._identification._id = request.form['id']
+    aliases = []
+    if request.form['id_aliases']:
+        aliases = [a.strip() for a in request.form['id_aliases'].split(',')]
+    tracking._identification._aliases = aliases
+    tracking._status = request.form['status']
+    tracking._version = parseVersion(request.form['version'])
+    tracking._initialDate = parseDate(request.form['initial'])
+    tracking._currentDate = parseDate(request.form['current'])
+    if wasNone:
+        get_current().setTracking(tracking)
+    if (not request.form['gen_engine']) and (not request.form['gen_date']):
+        generator = None
+    else:
+        generator._engine = request.form['gen_engine'] or None
+        if request.form['gen_date']:
+            generator._date = parseDate(request.form['gen_date'])
+        else:
+            generator._date = None
+    tracking.setGenerator(generator)
+    return redirect(url_for('document'))
+
+@app.route('/revision/<int:index>/edit', methods=['GET', 'POST'])
+@document_required
+def edit_revision(index):
+    cvrf = get_current()
+    if cvrf._tracking is None:
+        abort(404)
+    try:
+        revision = cvrf._tracking._history[index]
+    except IndexError:
+        abort(404)
+    if request.method != 'POST':
+        return render_template('edit_revision.j2', number='.'.join('%s'%v for v in revision._number), date=revision._date, description=revision._description, action='Update')
+
+    revision._number = parseVersion(request.form['number'])
+    revision._date = parseDate(request.form['date'])
+    revision._description = request.form['description']
+    return redirect(url_for('document'))
+
+@app.route('/revision/add', methods=['GET', 'POST'])
+@document_required
+def add_revision():
+    tracking = get_current()._tracking
+    if request.method != 'POST':
+        version = tracking._version
+        version = version[:-1] + (version[-1] + 1,)
+        return render_template('edit_revision.j2', number='.'.join("%d"%v for v in version), date=utcnow(), action='Add')
+
+    version = parseVersion(request.form['number'])
+    date = parseDate(request.form['date'])
+    revision = CVRFRevision(version, date, request.form['description'])
+    tracking.addRevision(revision)
+    if 'update_tracking' in request.form:
+        tracking._version = version
+        tracking._currentDate = date
+    return redirect(url_for('document'))
+
+@app.route('/distribution/edit', methods=['GET', 'POST'])
+@document_required
+def edit_distribution():
+    if request.method != 'POST':
+        return render_template('edit_distribution.j2', distribution=get_current()._distribution)
+
+    get_current().setDistribution(request.form['distribution'])
+    return redirect(url_for('document'))
+
+@app.route('/severity/edit', methods=['GET', 'POST'])
+@document_required
+def edit_severity():
+    severity = get_current()._aggregateseverity
+    if severity is None:
+        severity = CVRFAggregateSeverity('')
+    if request.method != 'POST':
+        return render_template('edit_severity.j2', severity=severity)
+    if not request.form['severity']:
+        severity = None
+    else:
+        severity._severity = request.form['severity']
+        severity.setNamespace(request.form['namespace'] or None)
+    get_current().setAggregateSeverity(severity)
+    return redirect(url_for('document'))
+
+@app.route('/note/<int:ordinal>')
+@document_required
+def view_note(ordinal):
+    note = get_current().getNote(ordinal)
+    if note is None:
+        abort(404)
+    return render_template('view_note.j2', note=note)
+
+@app.route('/note/<int:ordinal>/edit', methods=['GET', 'POST'])
+@document_required
+def edit_note(ordinal):
+    note = get_current().getNote(ordinal)
+    if note is None:
+        abort(404)
+    if request.method != 'POST':
+        return render_template('edit_note.j2', note=note, types = note.TYPES)
+
+    note._type = request.form['type']
+    note._ordinal = int(request.form['ordinal'])
+    note._note = request.form['note']
+    note._title = request.form['title'] or None
+    note._audience = request.form['audience'] or None
+    return redirect(url_for('view_note', ordinal=note._ordinal ))
+
+
+@app.route('/note/add', methods=['GET', 'POST'])
+@document_required
+def add_note():
+    if request.method != 'POST':
+        next_ordinal = 1
+        notes = get_current()._notes
+        if notes:
+            next_ordinal = notes[-1]._ordinal + 1
+        return render_template('edit_note.j2', ordinal=next_ordinal, types=CVRFNote.TYPES, action='Add')
+
+    title = None
+    audience = None
+    title = request.form['title'] or None
+    audience = request.form['audience'] or None
+
+    note = CVRFNote(request.form['type'], int(request.form['ordinal']), request.form['note'], title, audience)
+    get_current().addNote(note)
+    return redirect(url_for('document'))
+
+@app.route('/reference/<int:index>/edit', methods=['GET', 'POST'])
+@document_required
+def edit_reference(index):
+    try:
+        ref = get_current()._references[index]
+    except IndexError:
+        abort(404)
+    if request.method != 'POST':
+        return render_template('edit_reference.j2', _type=ref._type, url=ref._url, description=ref._description, types=('',) + ref.TYPES)
+
+    ref._type = request.form['type'] or None
+    ref._url = request.form['url']
+    ref._description = request.form['description']
+    return redirect(url_for('document'))
+
+
+@app.route('/reference/add', methods=['GET', 'POST'])
+@document_required
+def add_reference():
+    if request.method != 'POST':
+        return render_template('edit_reference.j2', action='Add', types=('',) + CVRFReference.TYPES)
+
+    ref = CVRFReference(request.form['url'], request.form['description'], request.form['type'] or None)
+    get_current().addReference(ref)
+    return redirect(url_for('document'))
+
+@app.route('/acknowledgment/<int:index>')
+@document_required
+def view_acknowledgment(index):
+    try:
+        ack = get_current()._acknowledgments[index]
+    except IndexError:
+        abort(404)
+    return render_template('view_acknowledgment.j2', acknowledgment=ack, index=index, action='Update')
+
+@app.route('/acknowledgment/<int:index>/edit', methods=['GET', 'POST'])
+@document_required
+def edit_acknowledgment(index):
+    try:
+        ack = get_current()._acknowledgments[index]
+    except IndexError:
+        abort(404)
+    if request.method != 'POST':
+        return render_template('edit_acknowledgment.j2', name=ack._name, organization=ack._organization, description=ack._description, url=ack._url, action='Update')
+
+    ack._name = request.form['name'] or None
+    ack._organization = request.form['organization'] or None
+    ack._description = request.form['description'] or None
+    ack._url = request.form['url'] or None
+    return redirect(url_for('document'))
+
+@app.route('/acknowledgment/add', methods=['GET', 'POST'])
+@document_required
+def add_acknowledgment():
+    if request.method != 'POST':
+        return render_template('edit_acknowledgment.j2', action='Add')
+
+    ack = CVRFAcknowledgment()
+    ack._name = request.form['name'] or None
+    ack._organization = request.form['organization'] or None
+    ack._description = request.form['description'] or None
+    ack._url = request.form['url'] or None
+    get_current().addAcknowledgment(ack)
+    return redirect(url_for('document'))
+
+
+@app.route('/render/<format_>')
+@document_required
+def render(format_):
+    cvrf = get_current()
+    doc = render_cvrf(cvrf, format_ + '.j2')
+    return render_template('render.j2', format_=format_, title=cvrf._title, type_=cvrf._type, doc=doc )
+
+@app.route('/save', methods=['GET', 'POST'])
+@document_required
+def save():
+    if request.method != 'POST':
+        return render_template('save.j2', id_=get_current()._tracking._identification._id)
+    # Get some kind of filename, and save the cvrf on cache (disk)
+    path = secure_filename(request.form['fname'])
+    path, _ = os.path.splitext(path)
+    with open(os.path.join(app.config['CACHE_DIRECTORY'], path + '.xml'), 'wt') as f:
+        f.write(render_cvrf(get_current(), 'cvrf.j2').encode('utf-8'))
+    flash('File saved as %s' % path)
+    del_current()
+    return redirect(url_for('new'))
+
+@app.route('/load/<element>', methods=['GET', 'POST'])
+def load(element):
+    if request.method != 'POST':
+        if has_current():
+            # Suggest to save first
+            return render_template('load.j2', element=element)
+
+    fpath = os.path.join(app.config['CACHE_DIRECTORY'], element+'.xml')
+    with open(fpath, 'rt') as f:
+        set_current(parse(f))
+    os.remove(fpath)
+    flash('"%s" has been removed from cache' % element)
+    # Get some kind of id, and load the file.
+    return redirect(url_for('document'))
+
+@app.route('/about')
+def about():
+    return render_template('about.j2')
+

http://farol.wald.intevation.org