Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 1 addition & 10 deletions test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@anthraxx do you mind double checking this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should leave this out for now, for sure it should be in a separate commit.



@pytest.fixture(scope='function')
Expand Down
51 changes: 46 additions & 5 deletions test/test_group.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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')
Expand Down Expand Up @@ -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'<h1>{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')
2 changes: 1 addition & 1 deletion tracker/templates/group.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ <h1>{{ group.name }}
{%- if group.bug_ticket %}
<td>{{ bug_ticket(group.bug_ticket) }}</td>
{%- elif group.status == "Vulnerable" %}
<td><a class='button button-table button-primary' href="https://bugs.archlinux.org/newtask?{{ bug_data | urlencode }}", accesskey='t'>Create</a></td>
<td><a class='button button-table button-primary' href="{{ url_for('tracker.create_bug_ticket_redirect', avg=group.name) }}" accesskey='t'>Create</a></td>
{%- else %}
<td>None</td>
{%- endif %}
Expand Down
71 changes: 41 additions & 30 deletions tracker/view/show.py
Original file line number Diff line number Diff line change
@@ -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_
Expand Down Expand Up @@ -38,32 +40,20 @@
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
from tracker.user import user_can_edit_issue
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)
Expand All @@ -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
}

Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -592,3 +566,40 @@ def show_log(page=1):
CVE=CVE,
CVEGroup=CVEGroup,
Advisory=Advisory)


@tracker.route('/group/<regex("{}"):avg>/create_bug'.format(vulnerability_group_regex[1:-1]), methods=['GET'])
@tracker.route('/avg/<regex("{}"):avg>/create_bug'.format(vulnerability_group_regex[1:-1]), methods=['GET'])
@tracker.route('/<regex("{}"):avg>/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"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gitlab uses a special logic to encode special characters, we need that here too Basically this.


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)