Mercurial > farol > farol
annotate farol/producttree.py @ 84:cc836f9e869e
Allow deletion of Products
author | Benoît Allard <benoit.allard@greenbone.net> |
---|---|
date | Thu, 09 Oct 2014 14:26:59 +0200 |
parents | 2ecf13200e87 |
children | b6a48669edb8 |
rev | line source |
---|---|
0 | 1 # -*- encoding: utf-8 -*- |
2 # Description: | |
3 # Web stuff about the ProductTree | |
4 # | |
5 # Authors: | |
6 # BenoƮt Allard <benoit.allard@greenbone.net> | |
7 # | |
8 # Copyright: | |
9 # Copyright (C) 2014 Greenbone Networks GmbH | |
10 # | |
11 # This program is free software; you can redistribute it and/or | |
12 # modify it under the terms of the GNU General Public License | |
13 # as published by the Free Software Foundation; either version 2 | |
14 # of the License, or (at your option) any later version. | |
15 # | |
16 # This program is distributed in the hope that it will be useful, | |
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 # GNU General Public License for more details. | |
20 # | |
21 # You should have received a copy of the GNU General Public License | |
22 # along with this program; if not, write to the Free Software | |
23 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
24 | |
25 """\ | |
26 Web-stuff about the producttree | |
27 """ | |
28 | |
29 from functools import wraps | |
30 | |
31 from flask import Blueprint, render_template, redirect, url_for, abort, request, flash | |
32 | |
33 from farolluz.cvrf import (CVRFProductBranch, CVRFFullProductName, | |
34 CVRFRelationship, CVRFGroup) | |
35 from .session import document_required, get_current | |
36 | |
37 producttree = Blueprint('producttree', __name__) | |
38 | |
39 def producttree_required(f): | |
40 @wraps(f) | |
41 def decorated_function(*args, **kwargs): | |
42 if get_current()._producttree is None: | |
43 flash('Operation invalid without producttree', 'warning') | |
22
dbfe89e3c6fe
Fix producttree urls
Benoît Allard <benoit.allard@greenbone.net>
parents:
0
diff
changeset
|
44 return redirect(url_for('document.view')) |
0 | 45 return f(*args, **kwargs) |
46 return decorated_function | |
47 | |
48 @producttree.route('/create', methods=['POST']) | |
49 @document_required | |
50 def create(): | |
51 get_current().createProductTree() | |
45
7c4d001839e7
Move the Display of the ProductTree to its own page
Benoît Allard <benoit.allard@greenbone.net>
parents:
22
diff
changeset
|
52 return redirect(url_for('.view')) |
0 | 53 |
45
7c4d001839e7
Move the Display of the ProductTree to its own page
Benoît Allard <benoit.allard@greenbone.net>
parents:
22
diff
changeset
|
54 @producttree.route('/') |
7c4d001839e7
Move the Display of the ProductTree to its own page
Benoît Allard <benoit.allard@greenbone.net>
parents:
22
diff
changeset
|
55 @document_required |
7c4d001839e7
Move the Display of the ProductTree to its own page
Benoît Allard <benoit.allard@greenbone.net>
parents:
22
diff
changeset
|
56 @producttree_required |
7c4d001839e7
Move the Display of the ProductTree to its own page
Benoît Allard <benoit.allard@greenbone.net>
parents:
22
diff
changeset
|
57 def view(): |
7c4d001839e7
Move the Display of the ProductTree to its own page
Benoît Allard <benoit.allard@greenbone.net>
parents:
22
diff
changeset
|
58 return render_template('producttree/view.j2', |
7c4d001839e7
Move the Display of the ProductTree to its own page
Benoît Allard <benoit.allard@greenbone.net>
parents:
22
diff
changeset
|
59 producttree=get_current()._producttree) |
0 | 60 |
61 @producttree.route('/branch/<path:path>/edit', methods=['GET', 'POST']) | |
62 @document_required | |
63 @producttree_required | |
64 def edit_branch(path): | |
65 path = [int(p) for p in path.split('/')] | |
66 cvrf = get_current() | |
67 ptree = cvrf._producttree | |
78
264d4579f6bf
More input validation
Benoît Allard <benoit.allard@greenbone.net>
parents:
62
diff
changeset
|
68 try: branch = cvrf._producttree.getBranch(path) |
264d4579f6bf
More input validation
Benoît Allard <benoit.allard@greenbone.net>
parents:
62
diff
changeset
|
69 except (ValueError, IndexError): abort(404) |
0 | 70 if request.method != 'POST': |
71 branches = [('', '')] + [(b.getName(), b.getPath(True)) for b in ptree.getNotTerminalBranches(branch)] | |
72 return render_template('producttree/edit_branch.j2', branch=branch, branches=branches, types=branch.TYPES) | |
73 | |
74 pbranch = ptree | |
75 if request.form['parent']: | |
78
264d4579f6bf
More input validation
Benoît Allard <benoit.allard@greenbone.net>
parents:
62
diff
changeset
|
76 try: pbranch = ptree.getBranch([int(p) for p in request.form['parent'].split('/')]) |
264d4579f6bf
More input validation
Benoît Allard <benoit.allard@greenbone.net>
parents:
62
diff
changeset
|
77 except (ValueError, IndexError): abort(404) |
0 | 78 |
79 if pbranch is not branch.getParent(): | |
80 # We have to 're-link' the element ... | |
81 # 1. unlink | |
82 branch.unlink() | |
83 # 2. set the new parent | |
82
d6fa288e92a7
Update to latest farolluz (unlink/link)
Benoît Allard <benoit.allard@greenbone.net>
parents:
80
diff
changeset
|
84 branch.link(pbranch) |
0 | 85 |
86 branch._type = request.form['type'] | |
87 branch._name = request.form['name'] | |
45
7c4d001839e7
Move the Display of the ProductTree to its own page
Benoît Allard <benoit.allard@greenbone.net>
parents:
22
diff
changeset
|
88 return redirect(url_for('.view')) |
0 | 89 |
90 @producttree.route('/branch/add', methods=['GET', 'POST']) | |
91 @document_required | |
92 @producttree_required | |
93 def add_branch(): | |
94 cvrf = get_current() | |
95 ptree = cvrf._producttree | |
96 if request.method != 'POST': | |
97 branches = [('', '')] + [(b.getName(), b.getPath(True)) for b in ptree.getNotTerminalBranches()] | |
98 return render_template('producttree/edit_branch.j2', branch=CVRFProductBranch('', '', ptree), action='Add', branches=branches, types=CVRFProductBranch.TYPES) | |
99 | |
100 pbranch = ptree | |
101 if request.form['parent']: | |
78
264d4579f6bf
More input validation
Benoît Allard <benoit.allard@greenbone.net>
parents:
62
diff
changeset
|
102 try: pbranch = ptree.getBranch([int(p) for p in request.form['parent'].split('/')]) |
264d4579f6bf
More input validation
Benoît Allard <benoit.allard@greenbone.net>
parents:
62
diff
changeset
|
103 except (ValueError, IndexError): abort(404) |
0 | 104 branch = CVRFProductBranch(request.form['type'], request.form['name'], pbranch) |
45
7c4d001839e7
Move the Display of the ProductTree to its own page
Benoît Allard <benoit.allard@greenbone.net>
parents:
22
diff
changeset
|
105 return redirect(url_for('.view')) |
0 | 106 |
80
c00f20bd90ba
Allow deletion of (orphaned) Branches
Benoît Allard <benoit.allard@greenbone.net>
parents:
78
diff
changeset
|
107 @producttree.route('/branch/<path:path>/del', methods=['POST']) |
c00f20bd90ba
Allow deletion of (orphaned) Branches
Benoît Allard <benoit.allard@greenbone.net>
parents:
78
diff
changeset
|
108 @document_required |
c00f20bd90ba
Allow deletion of (orphaned) Branches
Benoît Allard <benoit.allard@greenbone.net>
parents:
78
diff
changeset
|
109 @producttree_required |
c00f20bd90ba
Allow deletion of (orphaned) Branches
Benoît Allard <benoit.allard@greenbone.net>
parents:
78
diff
changeset
|
110 def del_branch(path): |
c00f20bd90ba
Allow deletion of (orphaned) Branches
Benoît Allard <benoit.allard@greenbone.net>
parents:
78
diff
changeset
|
111 path = [int(p) for p in path.split('/')] |
c00f20bd90ba
Allow deletion of (orphaned) Branches
Benoît Allard <benoit.allard@greenbone.net>
parents:
78
diff
changeset
|
112 cvrf = get_current() |
c00f20bd90ba
Allow deletion of (orphaned) Branches
Benoît Allard <benoit.allard@greenbone.net>
parents:
78
diff
changeset
|
113 ptree = cvrf._producttree |
c00f20bd90ba
Allow deletion of (orphaned) Branches
Benoît Allard <benoit.allard@greenbone.net>
parents:
78
diff
changeset
|
114 try: branch = cvrf._producttree.getBranch(path) |
c00f20bd90ba
Allow deletion of (orphaned) Branches
Benoît Allard <benoit.allard@greenbone.net>
parents:
78
diff
changeset
|
115 except (ValueError, IndexError): |
c00f20bd90ba
Allow deletion of (orphaned) Branches
Benoît Allard <benoit.allard@greenbone.net>
parents:
78
diff
changeset
|
116 flash('Cannot find Branch', 'danger') |
c00f20bd90ba
Allow deletion of (orphaned) Branches
Benoît Allard <benoit.allard@greenbone.net>
parents:
78
diff
changeset
|
117 abort(404) |
c00f20bd90ba
Allow deletion of (orphaned) Branches
Benoît Allard <benoit.allard@greenbone.net>
parents:
78
diff
changeset
|
118 if branch._childs: |
c00f20bd90ba
Allow deletion of (orphaned) Branches
Benoît Allard <benoit.allard@greenbone.net>
parents:
78
diff
changeset
|
119 flash('Cannot delete a branch with childs', 'danger') |
c00f20bd90ba
Allow deletion of (orphaned) Branches
Benoît Allard <benoit.allard@greenbone.net>
parents:
78
diff
changeset
|
120 abort(403) |
c00f20bd90ba
Allow deletion of (orphaned) Branches
Benoît Allard <benoit.allard@greenbone.net>
parents:
78
diff
changeset
|
121 branch.unlink() |
c00f20bd90ba
Allow deletion of (orphaned) Branches
Benoît Allard <benoit.allard@greenbone.net>
parents:
78
diff
changeset
|
122 del branch |
c00f20bd90ba
Allow deletion of (orphaned) Branches
Benoît Allard <benoit.allard@greenbone.net>
parents:
78
diff
changeset
|
123 return redirect(url_for('.view')) |
c00f20bd90ba
Allow deletion of (orphaned) Branches
Benoît Allard <benoit.allard@greenbone.net>
parents:
78
diff
changeset
|
124 |
c00f20bd90ba
Allow deletion of (orphaned) Branches
Benoît Allard <benoit.allard@greenbone.net>
parents:
78
diff
changeset
|
125 |
0 | 126 @producttree.route('/product/<productid>') |
127 @document_required | |
128 @producttree_required | |
129 def view_product(productid): | |
130 cvrf = get_current() | |
131 try: | |
132 product = cvrf.getProductForID(productid) | |
133 except IndexError: | |
134 abort(404) | |
135 return render_template('producttree/view_product.j2', product=product, cvrf=cvrf) | |
136 | |
137 @producttree.route('/product/<productid>/edit', methods=['GET', 'POST']) | |
138 @document_required | |
139 @producttree_required | |
140 def edit_product(productid): | |
141 cvrf = get_current() | |
142 ptree = cvrf._producttree | |
143 try: | |
144 product = cvrf.getProductForID(productid) | |
145 except KeyError: | |
146 abort(404) | |
147 | |
148 if request.method != 'POST': | |
149 current_rel = '' | |
150 if product.isRelationship(): | |
151 current_rel = str(ptree._relationships.index(product.getCurrentRelationship())) | |
152 leaves = [('', '')] + [(b.getName(), b.getPath(True)) for b in ptree.getOrphanedBranches(product)] | |
153 rels = [('', '')] + [(ptree.getNameOfRelationship(r), str(i)) for i, r in ptree.getOrphanedRelationships(product)] | |
154 return render_template('producttree/edit_product.j2', product=product, action='Update', orphaned_leaves=leaves, orphaned_relationships=rels, current_rel=current_rel) | |
155 | |
156 if request.form['parent_branch'] and request.form['parent_relationship']: | |
157 flash('Cannot set a parent branch and parent relationship', 'danger') | |
158 return redirect(url_for('.edit_product', productid=productid)) | |
159 | |
160 oldp = product._parent | |
161 if request.form['parent_branch']: | |
78
264d4579f6bf
More input validation
Benoît Allard <benoit.allard@greenbone.net>
parents:
62
diff
changeset
|
162 try: pbranch = ptree.getBranch([int(p) for p in request.form['parent_branch'].split('/')]) |
264d4579f6bf
More input validation
Benoît Allard <benoit.allard@greenbone.net>
parents:
62
diff
changeset
|
163 except (ValueError, IndexError): abort(404) |
0 | 164 if pbranch is not oldp: |
165 # Gonna be funny, needs re-link | |
166 product.unlink() | |
82
d6fa288e92a7
Update to latest farolluz (unlink/link)
Benoît Allard <benoit.allard@greenbone.net>
parents:
80
diff
changeset
|
167 # And Link again |
d6fa288e92a7
Update to latest farolluz (unlink/link)
Benoît Allard <benoit.allard@greenbone.net>
parents:
80
diff
changeset
|
168 product.link(pbranch) |
0 | 169 elif request.form['parent_relationship']: |
170 prel = ptree._relationships[int(request.form['parent_relationship'])] | |
171 if prel is not oldp: | |
82
d6fa288e92a7
Update to latest farolluz (unlink/link)
Benoît Allard <benoit.allard@greenbone.net>
parents:
80
diff
changeset
|
172 # Unlink |
0 | 173 product.unlink() |
82
d6fa288e92a7
Update to latest farolluz (unlink/link)
Benoît Allard <benoit.allard@greenbone.net>
parents:
80
diff
changeset
|
174 # Link again |
d6fa288e92a7
Update to latest farolluz (unlink/link)
Benoît Allard <benoit.allard@greenbone.net>
parents:
80
diff
changeset
|
175 product.link(prel) |
0 | 176 else: |
177 if ptree is not oldp: | |
82
d6fa288e92a7
Update to latest farolluz (unlink/link)
Benoît Allard <benoit.allard@greenbone.net>
parents:
80
diff
changeset
|
178 # Unlink |
0 | 179 product.unlink() |
82
d6fa288e92a7
Update to latest farolluz (unlink/link)
Benoît Allard <benoit.allard@greenbone.net>
parents:
80
diff
changeset
|
180 # Link again |
d6fa288e92a7
Update to latest farolluz (unlink/link)
Benoît Allard <benoit.allard@greenbone.net>
parents:
80
diff
changeset
|
181 product.link(ptree) |
0 | 182 |
183 product._productid = request.form['productid'] | |
184 product._name = request.form['name'] | |
185 product._cpe = request.form['cpe'] or None | |
45
7c4d001839e7
Move the Display of the ProductTree to its own page
Benoît Allard <benoit.allard@greenbone.net>
parents:
22
diff
changeset
|
186 return redirect(url_for('.view')) |
0 | 187 |
188 @producttree.route('/product/add', methods=['GET', 'POST']) | |
189 @document_required | |
190 @producttree_required | |
191 def add_product(): | |
192 cvrf = get_current() | |
193 ptree = cvrf._producttree | |
194 | |
195 if request.method != 'POST': | |
196 product=CVRFFullProductName('', '', ptree) | |
197 leaves = [('', '')] + [(b.getName(), b.getPath(True)) for b in ptree.getOrphanedBranches()] | |
198 rels = [('', '')] + [(ptree.getNameOfRelationship(r), str(i)) for i, r in ptree.getOrphanedRelationships()] | |
199 return render_template('producttree/edit_product.j2', product=product, action='Add', orphaned_leaves=leaves, orphaned_relationships=rels, current_rel='') | |
200 | |
201 if request.form['parent_branch'] and request.form['parent_relationship']: | |
202 flash('Cannot set a parent branch and parent relationship', 'danger') | |
62
ce49bd1512dd
Make pyflafes a happier
Benoît Allard <benoit.allard@greenbone.net>
parents:
45
diff
changeset
|
203 return redirect(url_for('.add_product')) |
0 | 204 |
205 parent = ptree | |
206 if request.form['parent_branch']: | |
83
2ecf13200e87
Fix issue from a previous commit
Benoît Allard <benoit.allard@greenbone.net>
parents:
82
diff
changeset
|
207 try: parent = ptree.getBranch([int(p) for p in request.form['parent_branch'].split('/')]) |
78
264d4579f6bf
More input validation
Benoît Allard <benoit.allard@greenbone.net>
parents:
62
diff
changeset
|
208 except (ValueError, IndexError): abort(404) |
0 | 209 elif request.form['parent_relationship']: |
210 parent = ptree._relationships[int(request.form['parent_relationship'])] | |
211 | |
212 product = CVRFFullProductName(request.form['productid'], request.form['name'], parent, request.form['cpe'] or None) | |
213 ptree.addProduct(product) | |
45
7c4d001839e7
Move the Display of the ProductTree to its own page
Benoît Allard <benoit.allard@greenbone.net>
parents:
22
diff
changeset
|
214 return redirect(url_for('.view')) |
0 | 215 |
84
cc836f9e869e
Allow deletion of Products
Benoît Allard <benoit.allard@greenbone.net>
parents:
83
diff
changeset
|
216 @producttree.route('/product/<productid>/del', methods=['POST']) |
cc836f9e869e
Allow deletion of Products
Benoît Allard <benoit.allard@greenbone.net>
parents:
83
diff
changeset
|
217 @document_required |
cc836f9e869e
Allow deletion of Products
Benoît Allard <benoit.allard@greenbone.net>
parents:
83
diff
changeset
|
218 @producttree_required |
cc836f9e869e
Allow deletion of Products
Benoît Allard <benoit.allard@greenbone.net>
parents:
83
diff
changeset
|
219 def del_product(productid): |
cc836f9e869e
Allow deletion of Products
Benoît Allard <benoit.allard@greenbone.net>
parents:
83
diff
changeset
|
220 cvrf = get_current() |
cc836f9e869e
Allow deletion of Products
Benoît Allard <benoit.allard@greenbone.net>
parents:
83
diff
changeset
|
221 ptree = cvrf._producttree |
cc836f9e869e
Allow deletion of Products
Benoît Allard <benoit.allard@greenbone.net>
parents:
83
diff
changeset
|
222 try: |
cc836f9e869e
Allow deletion of Products
Benoît Allard <benoit.allard@greenbone.net>
parents:
83
diff
changeset
|
223 product = cvrf.getProductForID(productid) |
cc836f9e869e
Allow deletion of Products
Benoît Allard <benoit.allard@greenbone.net>
parents:
83
diff
changeset
|
224 except KeyError: |
cc836f9e869e
Allow deletion of Products
Benoît Allard <benoit.allard@greenbone.net>
parents:
83
diff
changeset
|
225 abort(404) |
cc836f9e869e
Allow deletion of Products
Benoît Allard <benoit.allard@greenbone.net>
parents:
83
diff
changeset
|
226 product.unlink() |
cc836f9e869e
Allow deletion of Products
Benoît Allard <benoit.allard@greenbone.net>
parents:
83
diff
changeset
|
227 ptree._products.remove(product) |
cc836f9e869e
Allow deletion of Products
Benoît Allard <benoit.allard@greenbone.net>
parents:
83
diff
changeset
|
228 del product |
cc836f9e869e
Allow deletion of Products
Benoît Allard <benoit.allard@greenbone.net>
parents:
83
diff
changeset
|
229 return redirect(url_for('.view')) |
cc836f9e869e
Allow deletion of Products
Benoît Allard <benoit.allard@greenbone.net>
parents:
83
diff
changeset
|
230 |
cc836f9e869e
Allow deletion of Products
Benoît Allard <benoit.allard@greenbone.net>
parents:
83
diff
changeset
|
231 |
0 | 232 @producttree.route('/relationship/<int:index>/edit', methods=['GET', 'POST']) |
233 @document_required | |
234 @producttree_required | |
235 def edit_relationship(index): | |
236 cvrf = get_current() | |
237 ptree = cvrf._producttree | |
238 try: | |
239 rel = ptree._relationships[index] | |
240 except IndexError: | |
241 abort(404) | |
242 | |
243 if request.method != 'POST': | |
244 return render_template('producttree/edit_relationship.j2', productreference=rel._productreference, relationtype=rel._relationtype, relatestoproductreference=rel._relatestoproductreference, types=rel.TYPES) | |
245 | |
246 rel._productreference = request.form['productreference'] | |
247 rel._relationtype = request.form['relationtype'] | |
248 rel._relatestoproductreference = request.form['relatestoproductreference'] | |
45
7c4d001839e7
Move the Display of the ProductTree to its own page
Benoît Allard <benoit.allard@greenbone.net>
parents:
22
diff
changeset
|
249 return redirect(url_for('.view')) |
0 | 250 |
251 @producttree.route('/relationship/add', methods=['GET', 'POST']) | |
252 @document_required | |
253 @producttree_required | |
254 def add_relationship(): | |
255 cvrf = get_current() | |
256 ptree = cvrf._producttree | |
257 if len(ptree._products) < 2: | |
258 flash('You need to have at least two products to create a relationship', 'warning') | |
259 return redirect(url_for('.add_product')) | |
260 | |
261 if request.method != 'POST': | |
262 return render_template('producttree/edit_relationship.j2', action='Add', types=CVRFRelationship.TYPES) | |
263 | |
264 prodid1 = request.form['productreference'] | |
265 prodid2 = request.form['relatestoproductreference'] | |
266 | |
267 if prodid1 == prodid2: | |
268 flash('You cannot create a relationship with the same product twice', 'danger') | |
269 return redirect(url_for('.add_relationship')) | |
270 | |
271 rel = CVRFRelationship(prodid1, request.form['relationtype'], prodid2) | |
272 ptree.addRelationship(rel) | |
45
7c4d001839e7
Move the Display of the ProductTree to its own page
Benoît Allard <benoit.allard@greenbone.net>
parents:
22
diff
changeset
|
273 return redirect(url_for('.view')) |
0 | 274 |
275 @producttree.route('/group/<groupid>/edit', methods=['GET', 'POST']) | |
276 @document_required | |
277 @producttree_required | |
278 def edit_group(groupid): | |
279 try: | |
280 group = get_current().getGroupForID(groupid) | |
281 except KeyError: | |
282 abort(404) | |
283 if request.method != 'POST': | |
284 return render_template('producttree/edit_group.j2', groupid=group._groupid, description=group._description, productids=group._productids) | |
285 | |
286 group._groupid = request.form['groupid'] | |
287 group.setDescription(request.form['description'] or None) | |
288 group._productids = [] | |
289 for productid in request.form.getlist('products'): | |
290 group.addProductID(productid) | |
45
7c4d001839e7
Move the Display of the ProductTree to its own page
Benoît Allard <benoit.allard@greenbone.net>
parents:
22
diff
changeset
|
291 return redirect(url_for('.view')) |
0 | 292 |
293 @producttree.route('/group/add', methods=['GET', 'POST']) | |
294 @document_required | |
295 @producttree_required | |
296 def add_group(): | |
297 if request.method != 'POST': | |
298 return render_template('producttree/edit_group.j2', action='Add') | |
299 | |
300 group = CVRFGroup(request.form['groupid']) | |
301 group.setDescription(request.form['description'] or None) | |
302 for productid in request.form.getlist('products'): | |
303 group.addProductID(productid) | |
304 get_current()._producttree.addGroup(group) | |
45
7c4d001839e7
Move the Display of the ProductTree to its own page
Benoît Allard <benoit.allard@greenbone.net>
parents:
22
diff
changeset
|
305 return redirect(url_for('.view')) |