diff --git a/test/conftest.py b/test/conftest.py
index 3419d85..4b90133 100644
--- a/test/conftest.py
+++ b/test/conftest.py
@@ -63,22 +63,13 @@ def db(app, request):
@pytest.fixture(autouse=True, scope='function')
def run_scoped(app, db, client, request):
with app.app_context():
- connection = db.engine.connect()
- transaction = connection.begin()
-
- options = dict(bind=connection, binds={})
- session = db.create_scoped_session(options=options)
-
- db.session = session
db.create_all()
with client:
yield
+ db.session.remove()
db.drop_all()
- transaction.rollback()
- connection.close()
- session.remove()
@pytest.fixture(scope='function')
diff --git a/test/test_group.py b/test/test_group.py
index 7d62aa1..67667fb 100644
--- a/test/test_group.py
+++ b/test/test_group.py
@@ -1,3 +1,6 @@
+from urllib.parse import parse_qs
+from urllib.parse import urlparse
+
from flask import url_for
from werkzeug.exceptions import Forbidden
from werkzeug.exceptions import NotFound
@@ -11,7 +14,6 @@
from tracker.model.enum import UserRole
from tracker.model.enum import affected_to_status
from tracker.view.add import ERROR_GROUP_WITH_ISSUE_EXISTS
-from tracker.view.show import get_bug_project
from .conftest import DEFAULT_ADVISORY_ID
from .conftest import DEFAULT_GROUP_ID
@@ -59,10 +61,6 @@ def set_and_assert_group_data(db, client, route, pkgnames=['foo'], issues=['CVE-
if bug_ticket:
assert TRACKER_BUGTRACKER_URL.format(bug_ticket) in resp.data.decode('utf-8')
- else:
- # Assert project and product category
- project = get_bug_project([database])
- assert 'project={}&product_category=13'.format(project) in resp.data.decode('utf-8')
@create_package(name='foo')
@@ -481,3 +479,46 @@ def test_edit_group_does_nothing_when_data_is_same(db, client):
group = CVEGroup.query.get(DEFAULT_GROUP_ID)
assert group.changed == group_changed_old
+
+
+@create_package(name='foo', version='1.2.3-3')
+@create_group(id=DEFAULT_GROUP_ID, issues=[DEFAULT_ISSUE_ID], packages=['foo'], status=Status.vulnerable)
+@logged_in(role=UserRole.reporter)
+def test_create_bug_ticket_redirect_for_vulnerable_group(db, client):
+ """
+ Tests if clicking the 'Create' button for a vulnerable group correctly
+ redirects to a pre-filled GitLab 'New Issue' URL.
+ """
+ resp = client.get(url_for('tracker.create_bug_ticket_redirect', avg=DEFAULT_GROUP_NAME), follow_redirects=False)
+
+ assert 302 == resp.status_code
+
+ location = resp.location
+ parsed_url = urlparse(location)
+
+ assert 'gitlab.archlinux.org' == parsed_url.netloc
+ assert '/archlinux/packaging/packages/foo/-/issues/new' == parsed_url.path
+
+ query_params = parse_qs(parsed_url.query)
+ assert 'issue[title]' in query_params
+ assert 'issue[description]' in query_params
+
+ title = query_params['issue[title]'][0]
+ assert '[foo]' in title
+ assert '[Security]' in title
+ assert f'({DEFAULT_ISSUE_ID})' in title
+
+
+@create_package(name='foo', version='1.2.3-4')
+@create_group(id=DEFAULT_GROUP_ID, issues=[DEFAULT_ISSUE_ID], packages=['foo'], status=Status.fixed)
+@logged_in(role=UserRole.reporter)
+def test_create_bug_ticket_redirect_for_fixed_group_fails(db, client):
+ """
+ Tests that attempting to create a bug for a non-vulnerable group
+ redirects back to the group page with a flash message.
+ """
+ resp = client.get(url_for('tracker.create_bug_ticket_redirect', avg=DEFAULT_GROUP_NAME), follow_redirects=True)
+
+ assert 200 == resp.status_code
+ assert f'
{DEFAULT_GROUP_NAME}' in resp.data.decode('utf-8')
+ assert 'Bug ticket can only be created for vulnerable groups.' in resp.data.decode('utf-8')
diff --git a/tracker/templates/group.html b/tracker/templates/group.html
index 6d7f16e..645e66d 100644
--- a/tracker/templates/group.html
+++ b/tracker/templates/group.html
@@ -53,7 +53,7 @@ {{ group.name }}
{%- if group.bug_ticket %}
| {{ bug_ticket(group.bug_ticket) }} |
{%- elif group.status == "Vulnerable" %}
- Create |
+ Create |
{%- else %}
None |
{%- endif %}
diff --git a/tracker/view/show.py b/tracker/view/show.py
index 0e89a4b..847eb6b 100644
--- a/tracker/view/show.py
+++ b/tracker/view/show.py
@@ -1,8 +1,10 @@
from collections import OrderedDict
from collections import defaultdict
+from flask import flash
from flask import redirect
from flask import render_template
+from flask import url_for
from flask_login import current_user
from markupsafe import escape
from sqlalchemy import and_
@@ -38,6 +40,7 @@
from tracker.model.enum import Status
from tracker.model.package import filter_duplicate_packages
from tracker.model.package import sort_packages
+from tracker.user import reporter_required
from tracker.user import user_can_delete_group
from tracker.user import user_can_delete_issue
from tracker.user import user_can_edit_group
@@ -45,25 +48,12 @@
from tracker.user import user_can_handle_advisory
from tracker.user import user_can_watch_log
from tracker.user import user_can_watch_user_log
+from tracker.util import add_params_to_uri
from tracker.util import json_response
from tracker.util import multiline_to_list
from tracker.view.error import not_found
-def get_bug_project(databases):
- bug_project_mapping = {
- 1: ['core', 'core-testing', 'extra', 'extra-testing'],
- 5: ['multilib', 'multilib-testing']
- }
-
- for category, repos in bug_project_mapping.items():
- if all((database in repos for database in databases)):
- return category
-
- # Fallback
- return 1
-
-
def get_bug_data(cves, pkgs, versions, group):
references = []
references = [ref for ref in multiline_to_list(group.reference)
@@ -89,23 +79,8 @@ def get_bug_data(cves, pkgs, versions, group):
if TRACKER_SUMMARY_LENGTH_MAX != 0 and len(summary) > TRACKER_SUMMARY_LENGTH_MAX:
summary = "[{}] [Security] {} (Multiple CVE's)".format(pkg_str, group_type)
- # 5: critical, 4: high, 3: medium, 2: low, 1: very low.
- severitiy_mapping = {
- 'unknown': 3,
- 'critical': 5,
- 'high': 4,
- 'medium': 3,
- 'low': 2,
- }
-
- task_severity = severitiy_mapping.get(group.severity.name)
- project = get_bug_project((pkg.database for pkg in versions))
-
return {
- 'project': project,
- 'product_category': 13, # security
'item_summary': summary,
- 'task_severity': task_severity,
'detailed_desc': bug_desc
}
@@ -329,7 +304,6 @@ def show_group(avg):
versions=versions,
Status=Status,
issue_type=issue_type,
- bug_data=get_bug_data(issues, packages, versions, group),
advisories_pending=data['advisories_pending'],
can_edit=user_can_edit_group(advisories),
can_delete=user_can_delete_group(advisories),
@@ -592,3 +566,40 @@ def show_log(page=1):
CVE=CVE,
CVEGroup=CVEGroup,
Advisory=Advisory)
+
+
+@tracker.route('/group//create_bug'.format(vulnerability_group_regex[1:-1]), methods=['GET'])
+@tracker.route('/avg//create_bug'.format(vulnerability_group_regex[1:-1]), methods=['GET'])
+@tracker.route('//create_bug'.format(vulnerability_group_regex[1:-1]), methods=['GET'])
+@reporter_required
+def create_bug_ticket_redirect(avg):
+ data = get_group_data(avg)
+ if not data:
+ return not_found()
+
+ group = data['group']
+ issues = data['issues']
+ packages = data['packages']
+ versions = data['versions']
+
+ if group.status != Status.vulnerable:
+ flash('Bug ticket can only be created for vulnerable groups.', 'warning')
+ return redirect(url_for('tracker.show_group', avg=avg))
+
+ pkg_identifier = ''
+ if not versions:
+ pkg_identifier = packages[0].pkgname
+ else:
+ pkg_identifier = versions[0].base
+
+ pkgname = packages[0].pkgname
+ gitlab_url = f"https://gitlab.archlinux.org/archlinux/packaging/packages/{pkgname}/-/issues/new"
+
+ bug_data = get_bug_data(issues, packages, versions, group)
+ params = {
+ 'issue[title]': bug_data['item_summary'],
+ 'issue[description]': bug_data['detailed_desc']
+ }
+
+ final_url = add_params_to_uri(gitlab_url, params)
+ return redirect(final_url)