From 1a66d85e226b3612275a8d9d307c4ed4944bea33 Mon Sep 17 00:00:00 2001 From: Mark Reynolds Date: Nov 29 2016 14:36:19 +0000 Subject: Issue 1540 - New meta-data custom field type of "link" Added a new custom field type of "link", that is in addition to "boolean" and "text". Multiple links can be specified by separating them with commas. Then when rendering the the issues page, convert the value(s) to a hrefs Fixes https://pagure.io/pagure/issue/1540 --- diff --git a/pagure/lib/git.py b/pagure/lib/git.py index e0ac3d4..03fd140 100644 --- a/pagure/lib/git.py +++ b/pagure/lib/git.py @@ -472,7 +472,7 @@ def update_custom_field_from_json(session, repo, issue, json_data): def update_ticket_from_git( - session, reponame, namespace, username, issue_uid, json_data): + session, reponame, namespace, username, issue_uid, json_data): """ Update the specified issue (identified by its unique identifier) with the data present in the json blob provided. diff --git a/pagure/templates/issue.html b/pagure/templates/issue.html index 38dd952..e37534b 100644 --- a/pagure/templates/issue.html +++ b/pagure/templates/issue.html @@ -324,7 +324,16 @@

- {{ knowns_keys[field.name].value if field.name in knowns_keys }} + {% if field.name in knowns_keys %} + {% if field.key_type == 'link' %} + {% for link in knowns_keys[field.name].value.split(',') %} + {{ link }} +
+ {% endfor %} + {% else %} + {{ knowns_keys[field.name].value }} + {% endif %} + {% endif %}

diff --git a/pagure/templates/settings.html b/pagure/templates/settings.html index fe31308..c9bc445 100644 --- a/pagure/templates/settings.html +++ b/pagure/templates/settings.html @@ -708,6 +708,9 @@ + @@ -948,6 +951,7 @@ $('#new_custom_field').click(function(e) { \ \ ' diff --git a/pagure/ui/issues.py b/pagure/ui/issues.py index 82f1a49..8447598 100644 --- a/pagure/ui/issues.py +++ b/pagure/ui/issues.py @@ -25,6 +25,7 @@ from sqlalchemy.exc import SQLAlchemyError import kitchen.text.converters as ktc import mimetypes +import re import pagure.doc_utils import pagure.exceptions @@ -35,8 +36,55 @@ from pagure import (APP, SESSION, LOG, __get_file_in_tree, login_required, authenticated) +ip_middle_octet = u"(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5]))" +ip_last_octet = u"(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))" + +""" +regex based on https://github.com/kvesteri/validators/blob/master/validators/url.py +""" +urlregex = re.compile( + u"^" + # protocol identifier + u"(?:(?:https?|ftp)://)" + # user:pass authentication + u"(?:\S+(?::\S*)?@)?" + u"(?:" + u"(?P" + # IP address exclusion + # private & local networks + u"(?:(?:10|127)" + ip_middle_octet + u"{2}" + ip_last_octet + u")|" + u"(?:(?:169\.254|192\.168)" + ip_middle_octet + ip_last_octet + u")|" + u"(?:172\.(?:1[6-9]|2\d|3[0-1])" + ip_middle_octet + ip_last_octet + u"))" + u"|" + # IP address dotted notation octets + # excludes loopback network 0.0.0.0 + # excludes reserved space >= 224.0.0.0 + # excludes network & broadcast addresses + # (first & last IP address of each class) + u"(?P" + u"(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])" + u"" + ip_middle_octet + u"{2}" + u"" + ip_last_octet + u")" + u"|" + # host name + u"(?:(?:[a-z\u00a1-\uffff0-9]-?)*[a-z\u00a1-\uffff0-9]+)" + # domain name + u"(?:\.(?:[a-z\u00a1-\uffff0-9]-?)*[a-z\u00a1-\uffff0-9]+)*" + # TLD identifier + u"(?:\.(?:[a-z\u00a1-\uffff]{2,}))" + u")" + # port number + u"(?::\d{2,5})?" + # resource path + u"(?:/\S*)?" + u"$", + re.UNICODE | re.IGNORECASE +) +urlpattern = re.compile(urlregex) + # URLs + @APP.route( '//issue//update/', methods=['GET', 'POST']) @@ -269,10 +317,21 @@ def update_issue(repo, issueid, username=None, namespace=None): # Update the custom keys/fields for key in repo.issue_keys: value = flask.request.form.get(key.name) - messages.add( - pagure.lib.set_custom_key_value( - SESSION, issue, key, value) - ) + if value: + if key.key_type == 'link': + links = value.split(',') + for link in links: + link = link.replace(' ', '') + if not urlpattern.match(link): + flask.abort( + 400, + 'Meta-data "link" field ' + '(%s) has invalid url (%s) ' % + (key.name, link)) + messages.add( + pagure.lib.set_custom_key_value( + SESSION, issue, key, value) + ) # Update ticket this one depends on messages.union(set(pagure.lib.update_dependency_issue(