view farol/main.py @ 7:8f41bb7f4681

Move the Document management routines to a document Blueprint
author Benoît Allard <benoit.allard@greenbone.net>
date Thu, 25 Sep 2014 17:03:35 +0200
parents 3478e20885fd
children 2ce3676c9b2e
line wrap: on
line source
# -*- 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, ValidationError
from farolluz.parsers.cvrf import parse
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
from werkzeug import secure_filename

from .document import document
from .session import get_current, set_current, has_current, del_current, document_required
from .vulnerability import vulnerability
from .producttree import producttree
from .proxy import ReverseProxied

app = Flask(__name__, instance_relative_config=True)
app.config.from_object('farol.config.Config')
app.config.from_pyfile('farol.cfg', silent=True)

app.register_blueprint(document, url_prefix='/document')
app.register_blueprint(vulnerability, url_prefix='/vulnerability')
app.register_blueprint(producttree, url_prefix='/producttree')

app.wsgi_app = ReverseProxied(app.wsgi_app)

@app.context_processor
def cache_content():
    """ List the documents in cache """
    dirname = app.config.get('CACHE_DIRECTORY',
                             os.path.join(app.instance_path, '_cache'))
    if not os.path.exists(dirname):
        os.makedirs(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('/')
def welcome():
    return render_template('welcome.j2')

@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.view'))

@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)
    dirname = app.config.get('CACHE_DIRECTORY',
                             os.path.join(app.instance_path, '_cache'))
    with open(os.path.join(dirname, 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)

    dirname = app.config.get('CACHE_DIRECTORY',
                             os.path.join(app.instance_path, '_cache'))
    fpath = os.path.join(dirname, 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.view'))

@app.route('/about')
def about():
    return render_template('about.j2', instance_dir=app.instance_path)

http://farol.wald.intevation.org