- Backport various fixes from upstream
+ Patch: 0001-Display-real-line-numbers-on-pull-request-s-diff-vie.patch + Patch: 0002-Show-the-assignee-s-avatar-on-the-board.patch + Patch: 0003-Allow-setting-a-status-as-closing-even-if-the-projec.patch + Patch: 0004-Include-the-assignee-in-the-list-of-people-notified-.patch + Patch: 0005-Introduce-the-collaborator_project_groups-mapping.patch + Patch: 0006-When-a-file-a-detected-as-a-binary-file-return-the-r.patch + Patch: 0007-Remove-fenced-code-block-when-checking-mention.patch + Patch: 0008-Add-support-for-using-cchardet-to-detect-files-encod.patch + Patch: 0009-Add-support-for-disabling-user-registration.patch - Remove mandatory dependency on systemd to ease containerization OBS-URL: https://build.opensuse.org/package/show/devel:tools:scm/pagure?expand=0&rev=46
This commit is contained in:
parent
1623fbaef4
commit
a61ee7e487
194
0001-Display-real-line-numbers-on-pull-request-s-diff-vie.patch
Normal file
194
0001-Display-real-line-numbers-on-pull-request-s-diff-vie.patch
Normal file
@ -0,0 +1,194 @@
|
||||
From f48278682d9552670b7d5cb9e99a7e0a74bdd689 Mon Sep 17 00:00:00 2001
|
||||
From: Julen Landa Alustiza <jlanda@fedoraproject.org>
|
||||
Date: Fri, 7 Aug 2020 12:35:32 +0200
|
||||
Subject: [PATCH 1/9] Display real line numbers on pull request's diff view
|
||||
Fixes #724
|
||||
|
||||
---
|
||||
pagure/templates/_repo_renderdiff.html | 1 -
|
||||
pagure/ui/filters.py | 101 ++++++++++---------------
|
||||
tests/test_pagure_flask_ui_fork.py | 24 +++++-
|
||||
3 files changed, 64 insertions(+), 62 deletions(-)
|
||||
|
||||
diff --git a/pagure/templates/_repo_renderdiff.html b/pagure/templates/_repo_renderdiff.html
|
||||
index a0922169..aa9a062e 100644
|
||||
--- a/pagure/templates/_repo_renderdiff.html
|
||||
+++ b/pagure/templates/_repo_renderdiff.html
|
||||
@@ -164,7 +164,6 @@
|
||||
commit=patchstats["new_id"],
|
||||
prequest=pull_request,
|
||||
index=loop.index,
|
||||
- isprdiff=True,
|
||||
tree_id=diff_commits[0].tree.id)}}
|
||||
</div>
|
||||
{% endautoescape %}
|
||||
diff --git a/pagure/ui/filters.py b/pagure/ui/filters.py
|
||||
index 73799ed7..98b2741f 100644
|
||||
--- a/pagure/ui/filters.py
|
||||
+++ b/pagure/ui/filters.py
|
||||
@@ -149,38 +149,33 @@ def format_loc(
|
||||
for key in comments:
|
||||
comments[key] = sorted(comments[key], key=lambda obj: obj.date_created)
|
||||
|
||||
- if not index:
|
||||
- index = ""
|
||||
+ if isinstance(filename, str) and six.PY2:
|
||||
+ filename = filename.decode("UTF-8")
|
||||
|
||||
cnt = 1
|
||||
for line in loc.split("\n"):
|
||||
- if filename and commit:
|
||||
- if isinstance(filename, str) and six.PY2:
|
||||
- filename = filename.decode("UTF-8")
|
||||
-
|
||||
- if isprdiff and (
|
||||
- line.startswith("@@")
|
||||
- or line.startswith("+")
|
||||
- or line.startswith("-")
|
||||
- ):
|
||||
- if line.startswith("@@"):
|
||||
- output.append(
|
||||
- '<tr class="stretch-table-column bg-light"\
|
||||
- id="c-%(commit)s-%(cnt_lbl)s">'
|
||||
- % ({"cnt_lbl": cnt, "commit": commit})
|
||||
- )
|
||||
- elif line.startswith("+"):
|
||||
- output.append(
|
||||
- '<tr class="stretch-table-column alert-success" \
|
||||
- id="c-%(commit)s-%(cnt_lbl)s">'
|
||||
- % ({"cnt_lbl": cnt, "commit": commit})
|
||||
- )
|
||||
- elif line.startswith("-"):
|
||||
- output.append(
|
||||
- '<tr class="stretch-table-column alert-danger" \
|
||||
- id="c-%(commit)s-%(cnt_lbl)s">'
|
||||
- % ({"cnt_lbl": cnt, "commit": commit})
|
||||
- )
|
||||
+ if line.startswith("@@"):
|
||||
+ output.append(
|
||||
+ '<tr class="stretch-table-column bg-light"\
|
||||
+ id="c-%(commit)s-%(cnt_lbl)s">'
|
||||
+ % ({"cnt_lbl": cnt, "commit": commit})
|
||||
+ )
|
||||
+ output.append(
|
||||
+ '<td class="cell1"></td><td class="prc border-right"></td>'
|
||||
+ )
|
||||
+ else:
|
||||
+ if line.startswith("+"):
|
||||
+ output.append(
|
||||
+ '<tr class="stretch-table-column alert-success" \
|
||||
+ id="c-%(commit)s-%(cnt_lbl)s">'
|
||||
+ % ({"cnt_lbl": cnt, "commit": commit})
|
||||
+ )
|
||||
+ elif line.startswith("-"):
|
||||
+ output.append(
|
||||
+ '<tr class="stretch-table-column alert-danger" \
|
||||
+ id="c-%(commit)s-%(cnt_lbl)s">'
|
||||
+ % ({"cnt_lbl": cnt, "commit": commit})
|
||||
+ )
|
||||
else:
|
||||
output.append(
|
||||
'<tr id="c-%(commit)s-%(cnt_lbl)s">'
|
||||
@@ -211,13 +206,6 @@ def format_loc(
|
||||
}
|
||||
)
|
||||
)
|
||||
- else:
|
||||
- output.append(
|
||||
- '<tr><td class="cell1">'
|
||||
- '<a id="%(cnt)s" href="#%(cnt)s" data-line-number='
|
||||
- '"%(cnt_lbl)s"></a></td>'
|
||||
- % ({"cnt": "%s_%s" % (index, cnt), "cnt_lbl": cnt})
|
||||
- )
|
||||
|
||||
cnt += 1
|
||||
if not line:
|
||||
@@ -254,29 +242,24 @@ def format_loc(
|
||||
+ 'title="Open changed file"></span></a>'
|
||||
)
|
||||
|
||||
- if isprdiff and (
|
||||
- line.startswith("@@")
|
||||
- or line.startswith("+")
|
||||
- or line.startswith("-")
|
||||
- ):
|
||||
- if line.startswith("@@"):
|
||||
- output.append(
|
||||
- '<td class="cell2 stretch-table-column">\
|
||||
- <pre class="text-muted"><code>%s</code></pre></td>'
|
||||
- % line
|
||||
- )
|
||||
- elif line.startswith("+"):
|
||||
- output.append(
|
||||
- '<td class="cell2 stretch-table-column">\
|
||||
- <pre class="alert-success"><code>%s</code></pre></td>'
|
||||
- % escape(line)
|
||||
- )
|
||||
- elif line.startswith("-"):
|
||||
- output.append(
|
||||
- '<td class="cell2 stretch-table-column">\
|
||||
- <pre class="alert-danger"><code>%s</code></pre></td>'
|
||||
- % escape(line)
|
||||
- )
|
||||
+ if line.startswith("@@"):
|
||||
+ output.append(
|
||||
+ '<td class="cell2 stretch-table-column">\
|
||||
+ <pre class="text-muted"><code>%s</code></pre></td>'
|
||||
+ % line
|
||||
+ )
|
||||
+ elif line.startswith("+"):
|
||||
+ output.append(
|
||||
+ '<td class="cell2 stretch-table-column">\
|
||||
+ <pre class="alert-success"><code>%s</code></pre></td>'
|
||||
+ % escape(line)
|
||||
+ )
|
||||
+ elif line.startswith("-"):
|
||||
+ output.append(
|
||||
+ '<td class="cell2 stretch-table-column">\
|
||||
+ <pre class="alert-danger"><code>%s</code></pre></td>'
|
||||
+ % escape(line)
|
||||
+ )
|
||||
else:
|
||||
output.append(
|
||||
'<td class="cell2"><pre><code>%s</code></pre></td>'
|
||||
diff --git a/tests/test_pagure_flask_ui_fork.py b/tests/test_pagure_flask_ui_fork.py
|
||||
index 21ecd7df..8e8dce1c 100644
|
||||
--- a/tests/test_pagure_flask_ui_fork.py
|
||||
+++ b/tests/test_pagure_flask_ui_fork.py
|
||||
@@ -302,11 +302,31 @@ class PagureFlaskForktests(tests.Modeltests):
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
- '<span class="btn btn-success btn-sm font-weight-bold disabled opacity-100">+3</span>',
|
||||
+ '<span class="btn btn-success btn-sm font-weight-bold disabled'
|
||||
+ ' opacity-100">+3</span>',
|
||||
output_text,
|
||||
)
|
||||
self.assertIn(
|
||||
- '<span class="btn btn-danger btn-sm font-weight-bold disabled opacity-100">-1</span>',
|
||||
+ '<span class="btn btn-danger btn-sm font-weight-bold disabled '
|
||||
+ 'opacity-100">-1</span>',
|
||||
+ output_text,
|
||||
+ )
|
||||
+
|
||||
+ # Test if hunk headline is rendered without line numbers
|
||||
+ self.assertIn(
|
||||
+ '<td class="cell1"></td><td class="prc border-right"></td>\n<td '
|
||||
+ 'class="cell2 stretch-table-column"> <pre class='
|
||||
+ '"text-muted"><code>@@ -1,2 +1,4 @@',
|
||||
+ output_text,
|
||||
+ )
|
||||
+ # Tests if line number 1 is displayed
|
||||
+ self.assertNotIn(
|
||||
+ '<td class="cell1"><a id="_1__1" href="#_1__1" data-line-number="1" data-file-number="1"></a></td>',
|
||||
+ output_text,
|
||||
+ )
|
||||
+ # Test if line number 2 is displayed
|
||||
+ self.assertIn(
|
||||
+ '<td class="cell1"><a id="_1__2" href="#_1__2" data-line-number="2" data-file-number="1"></a></td>',
|
||||
output_text,
|
||||
)
|
||||
|
||||
--
|
||||
2.26.2
|
||||
|
33
0002-Show-the-assignee-s-avatar-on-the-board.patch
Normal file
33
0002-Show-the-assignee-s-avatar-on-the-board.patch
Normal file
@ -0,0 +1,33 @@
|
||||
From d3fb1c32746580bb109ac21ff349a655a01c46f0 Mon Sep 17 00:00:00 2001
|
||||
From: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||
Date: Wed, 12 Aug 2020 20:47:22 +0200
|
||||
Subject: [PATCH 2/9] Show the assignee's avatar on the board
|
||||
|
||||
If the ticket shown in the board is assigned to someone, show this
|
||||
person's avatar. This helps not only seeing what is in progress or
|
||||
blocked but also who is working on what or being blocked.
|
||||
|
||||
Fixes https://pagure.io/pagure/issue/4959
|
||||
|
||||
Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||
---
|
||||
pagure/templates/board.html | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/pagure/templates/board.html b/pagure/templates/board.html
|
||||
index 26509ae0..46a7eb65 100644
|
||||
--- a/pagure/templates/board.html
|
||||
+++ b/pagure/templates/board.html
|
||||
@@ -65,6 +65,9 @@
|
||||
{% elif bissue.issue.status == 'Closed' %}
|
||||
<span class="fa fa-fw text-danger fa-exclamation-circle pt-1 icon_id"></span>
|
||||
<span class="text-danger font-weight-bold id_txt">#{{ bissue.issue.id }}</span>
|
||||
+ {% endif %}
|
||||
+ {% if bissue.issue.assignee %}
|
||||
+ - {{ bissue.issue.assignee.username | avatar(size=20) | safe}}
|
||||
{% endif %}
|
||||
- {{ bissue.issue.title | truncate(80, False, '...') }}
|
||||
</a>
|
||||
--
|
||||
2.26.2
|
||||
|
128
0003-Allow-setting-a-status-as-closing-even-if-the-projec.patch
Normal file
128
0003-Allow-setting-a-status-as-closing-even-if-the-projec.patch
Normal file
@ -0,0 +1,128 @@
|
||||
From 9fd32d4d948fc4231eee68e8044b844060db140c Mon Sep 17 00:00:00 2001
|
||||
From: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||
Date: Wed, 12 Aug 2020 20:56:18 +0200
|
||||
Subject: [PATCH 3/9] Allow setting a status as closing even if the project has
|
||||
no close_status
|
||||
|
||||
When determining if a status "closes" tickets or not, we should first
|
||||
check if it was set to and only if it wasn't then check if there was a
|
||||
close_status set for it. Otherwise the logic wasn't correctly interpreted.
|
||||
|
||||
Fixes https://pagure.io/pagure/issue/4958
|
||||
|
||||
Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||
---
|
||||
pagure/api/boards.py | 4 +-
|
||||
tests/test_pagure_flask_api_boards.py | 81 +++++++++++++++++++++++++++
|
||||
2 files changed, 84 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/pagure/api/boards.py b/pagure/api/boards.py
|
||||
index e42f7cb6..669fd457 100644
|
||||
--- a/pagure/api/boards.py
|
||||
+++ b/pagure/api/boards.py
|
||||
@@ -510,7 +510,9 @@ def api_board_status(repo, board_name, username=None, namespace=None):
|
||||
|
||||
try:
|
||||
close_status = data[name].get("close_status") or None
|
||||
- close = data[name].get("close") or True if close_status else False
|
||||
+ close = data[name].get("close") or (
|
||||
+ True if close_status else False
|
||||
+ )
|
||||
if close_status not in repo.close_status:
|
||||
close_status = None
|
||||
|
||||
diff --git a/tests/test_pagure_flask_api_boards.py b/tests/test_pagure_flask_api_boards.py
|
||||
index ef125878..67199703 100644
|
||||
--- a/tests/test_pagure_flask_api_boards.py
|
||||
+++ b/tests/test_pagure_flask_api_boards.py
|
||||
@@ -801,6 +801,87 @@ class PagureFlaskApiBoardsWithBoardtests(tests.SimplePagureTest):
|
||||
},
|
||||
)
|
||||
|
||||
+ def test_api_board_api_board_status_no_close_status(self):
|
||||
+ headers = {
|
||||
+ "Authorization": "token aaabbbcccddd",
|
||||
+ "Content-Type": "application/json",
|
||||
+ }
|
||||
+
|
||||
+ data = json.dumps(
|
||||
+ {
|
||||
+ "Backlog": {
|
||||
+ "close": False,
|
||||
+ "close_status": None,
|
||||
+ "bg_color": "#FFB300",
|
||||
+ "default": True,
|
||||
+ "rank": 1,
|
||||
+ },
|
||||
+ "Triaged": {
|
||||
+ "close": False,
|
||||
+ "close_status": None,
|
||||
+ "bg_color": "#ca0dcd",
|
||||
+ "default": False,
|
||||
+ "rank": 2,
|
||||
+ },
|
||||
+ "Done": {
|
||||
+ "close": True,
|
||||
+ "close_status": None,
|
||||
+ "bg_color": "#34d240",
|
||||
+ "default": False,
|
||||
+ "rank": 4,
|
||||
+ },
|
||||
+ " ": {
|
||||
+ "close": True,
|
||||
+ "close_status": None,
|
||||
+ "bg_color": "#34d240",
|
||||
+ "default": False,
|
||||
+ "rank": 5,
|
||||
+ },
|
||||
+ }
|
||||
+ )
|
||||
+ output = self.app.post(
|
||||
+ "/api/0/test/boards/dev/status", headers=headers, data=data
|
||||
+ )
|
||||
+ self.assertEqual(output.status_code, 200)
|
||||
+ data = json.loads(output.get_data(as_text=True))
|
||||
+ self.assertDictEqual(
|
||||
+ data,
|
||||
+ {
|
||||
+ "board": {
|
||||
+ "active": True,
|
||||
+ "name": "dev",
|
||||
+ "status": [
|
||||
+ {
|
||||
+ "bg_color": "#FFB300",
|
||||
+ "close": False,
|
||||
+ "close_status": None,
|
||||
+ "default": True,
|
||||
+ "name": "Backlog",
|
||||
+ },
|
||||
+ {
|
||||
+ "bg_color": "#ca0dcd",
|
||||
+ "close": False,
|
||||
+ "close_status": None,
|
||||
+ "default": False,
|
||||
+ "name": "Triaged",
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Done",
|
||||
+ "close": True,
|
||||
+ "close_status": None,
|
||||
+ "default": False,
|
||||
+ "bg_color": "#34d240",
|
||||
+ },
|
||||
+ ],
|
||||
+ "tag": {
|
||||
+ "tag": "dev",
|
||||
+ "tag_color": "DeepBlueSky",
|
||||
+ "tag_description": "",
|
||||
+ },
|
||||
+ }
|
||||
+ },
|
||||
+ )
|
||||
+
|
||||
def test_api_board_api_board_status_adding_removing(self):
|
||||
headers = {
|
||||
"Authorization": "token aaabbbcccddd",
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,36 @@
|
||||
From 1e129038cf63f619fd5b69f92057cb29c53a83d3 Mon Sep 17 00:00:00 2001
|
||||
From: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||
Date: Wed, 12 Aug 2020 21:19:22 +0200
|
||||
Subject: [PATCH 4/9] Include the assignee in the list of people notified on a
|
||||
ticket/PR
|
||||
|
||||
We always include the assignee in the notifications (even on private
|
||||
tickets), but so far we did not show them in the list of subscriber.
|
||||
|
||||
With this commit, this oversight is now fixed.
|
||||
|
||||
Fixes https://pagure.io/pagure/issue/4957
|
||||
|
||||
Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||
---
|
||||
pagure/lib/query.py | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/pagure/lib/query.py b/pagure/lib/query.py
|
||||
index 8ee4df6c..498148df 100644
|
||||
--- a/pagure/lib/query.py
|
||||
+++ b/pagure/lib/query.py
|
||||
@@ -4957,6 +4957,10 @@ def get_watch_list(session, obj):
|
||||
# Add the user of the project
|
||||
users.add(obj.project.user.username)
|
||||
|
||||
+ # Add the assignee if there is one
|
||||
+ if obj.assignee:
|
||||
+ users.add(obj.assignee.username)
|
||||
+
|
||||
# Add the regular contributors
|
||||
for contributor in obj.project.users:
|
||||
users.add(contributor.username)
|
||||
--
|
||||
2.26.2
|
||||
|
104
0005-Introduce-the-collaborator_project_groups-mapping.patch
Normal file
104
0005-Introduce-the-collaborator_project_groups-mapping.patch
Normal file
@ -0,0 +1,104 @@
|
||||
From d91182e9bd01582c3ba1671a758038819943fb9b Mon Sep 17 00:00:00 2001
|
||||
From: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||
Date: Tue, 18 Aug 2020 13:33:21 +0200
|
||||
Subject: [PATCH 5/9] Introduce the collaborator_project_groups mapping
|
||||
|
||||
We need two mappings on a regular basis. One linking a project to its
|
||||
group of collaborator and pointing to the PagureGroup objects directly.
|
||||
This is used for example to retrieve the list of collaborator groups.
|
||||
The one mapping is between a project and the corresponding ProjectGroup
|
||||
for collaborators which is where the "branches" that the group is
|
||||
restricted to is stored.
|
||||
|
||||
So we now have both mappings available and we need to be careful to use
|
||||
the proper one, but pagure will quickly indicate (ie: crash) if one
|
||||
uses the wrong one and tries to access either the group name or the
|
||||
branches attribute.
|
||||
|
||||
Fixes https://pagure.io/fedora-infrastructure/issue/9247
|
||||
|
||||
Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||
---
|
||||
pagure/lib/model.py | 10 ++++++++++
|
||||
pagure/utils.py | 2 +-
|
||||
tests/test_pagure_flask_api_project.py | 23 ++++++++++++++++++++++-
|
||||
3 files changed, 33 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/pagure/lib/model.py b/pagure/lib/model.py
|
||||
index 325a5452..4eea9f58 100644
|
||||
--- a/pagure/lib/model.py
|
||||
+++ b/pagure/lib/model.py
|
||||
@@ -487,6 +487,16 @@ class Project(BASE):
|
||||
)
|
||||
|
||||
collaborator_groups = relation(
|
||||
+ "PagureGroup",
|
||||
+ secondary="projects_groups",
|
||||
+ primaryjoin="projects.c.id==projects_groups.c.project_id",
|
||||
+ secondaryjoin="and_(pagure_group.c.id==projects_groups.c.group_id,\
|
||||
+ projects_groups.c.access=='collaborator')",
|
||||
+ order_by="PagureGroup.group_name.asc()",
|
||||
+ viewonly=True,
|
||||
+ )
|
||||
+
|
||||
+ collaborator_project_groups = relation(
|
||||
"ProjectGroup",
|
||||
primaryjoin="and_(projects.c.id==projects_groups.c.project_id,\
|
||||
projects_groups.c.access=='collaborator')",
|
||||
diff --git a/pagure/utils.py b/pagure/utils.py
|
||||
index 24a0ce4d..915ba499 100644
|
||||
--- a/pagure/utils.py
|
||||
+++ b/pagure/utils.py
|
||||
@@ -311,7 +311,7 @@ def is_repo_collaborator(repo_obj, refname, username=None, session=None):
|
||||
return True
|
||||
|
||||
# If they are in a group that has commit access -> maybe
|
||||
- for project_group in repo_obj.collaborator_groups:
|
||||
+ for project_group in repo_obj.collaborator_project_groups:
|
||||
if project_group.group.group_name in usergroups:
|
||||
# if branch is None when the user tries to read,
|
||||
# so we'll allow that
|
||||
diff --git a/tests/test_pagure_flask_api_project.py b/tests/test_pagure_flask_api_project.py
|
||||
index 3c364be2..51dd8e9f 100644
|
||||
--- a/tests/test_pagure_flask_api_project.py
|
||||
+++ b/tests/test_pagure_flask_api_project.py
|
||||
@@ -1010,6 +1010,27 @@ class PagureFlaskApiProjecttests(tests.Modeltests):
|
||||
)
|
||||
self.session.commit()
|
||||
|
||||
+ # Add a collaborator group
|
||||
+ msg = pagure.lib.query.add_group(
|
||||
+ self.session,
|
||||
+ group_name="some_group",
|
||||
+ display_name="Some Group",
|
||||
+ description=None,
|
||||
+ group_type="bar",
|
||||
+ user="pingou",
|
||||
+ is_admin=False,
|
||||
+ blacklist=[],
|
||||
+ )
|
||||
+ pagure.lib.query.add_group_to_project(
|
||||
+ session=self.session,
|
||||
+ project=project,
|
||||
+ new_group="some_group",
|
||||
+ user="pingou",
|
||||
+ access="collaborator",
|
||||
+ branches="features/*",
|
||||
+ )
|
||||
+ self.session.commit()
|
||||
+
|
||||
# Existing project
|
||||
output = self.app.get("/api/0/test")
|
||||
self.assertEqual(output.status_code, 200)
|
||||
@@ -1019,7 +1040,7 @@ class PagureFlaskApiProjecttests(tests.Modeltests):
|
||||
expected_data = {
|
||||
"access_groups": {
|
||||
"admin": [],
|
||||
- "collaborator": [],
|
||||
+ "collaborator": ["some_group"],
|
||||
"commit": [],
|
||||
"ticket": [],
|
||||
},
|
||||
--
|
||||
2.26.2
|
||||
|
219
0006-When-a-file-a-detected-as-a-binary-file-return-the-r.patch
Normal file
219
0006-When-a-file-a-detected-as-a-binary-file-return-the-r.patch
Normal file
@ -0,0 +1,219 @@
|
||||
From 3f65d123faa3a1fcd0b93921e5d42fe659b79fa7 Mon Sep 17 00:00:00 2001
|
||||
From: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||
Date: Wed, 12 Aug 2020 21:33:07 +0200
|
||||
Subject: [PATCH 6/9] When a file a detected as a binary file, return the raw
|
||||
file
|
||||
|
||||
Basically, with the code until now, if an user was trying to view
|
||||
a binary file in the UI, it was then prompted to download the file
|
||||
(as pagure doesn't know how to display binary file), but the file
|
||||
the users were downloading wasn't the raw file but rather the html
|
||||
page that would contain the file.
|
||||
Not ideal.
|
||||
|
||||
So with this commit we're now just saying: if the file is binary and
|
||||
we can't render it, just return the raw file to the user and let
|
||||
them deal with it.
|
||||
|
||||
Fixes https://pagure.io/pagure/issue/4907
|
||||
|
||||
Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||
---
|
||||
pagure/ui/repo.py | 8 +++-
|
||||
tests/test_pagure_flask_ui_fork.py | 18 ++-------
|
||||
tests/test_pagure_flask_ui_repo.py | 25 ++++---------
|
||||
tests/test_pagure_flask_ui_repo_view_file.py | 39 +++++++++-----------
|
||||
4 files changed, 35 insertions(+), 55 deletions(-)
|
||||
|
||||
diff --git a/pagure/ui/repo.py b/pagure/ui/repo.py
|
||||
index b6aacc8e..06afb71d 100644
|
||||
--- a/pagure/ui/repo.py
|
||||
+++ b/pagure/ui/repo.py
|
||||
@@ -639,7 +639,13 @@ def view_file(repo, identifier, filename, username=None, namespace=None):
|
||||
output_type = "tree"
|
||||
|
||||
if output_type == "binary":
|
||||
- headers[str("Content-Disposition")] = "attachment"
|
||||
+ return view_raw_file(
|
||||
+ repo,
|
||||
+ identifier,
|
||||
+ filename=filename,
|
||||
+ username=username,
|
||||
+ namespace=namespace,
|
||||
+ )
|
||||
|
||||
return flask.Response(
|
||||
flask.stream_with_context(
|
||||
diff --git a/tests/test_pagure_flask_ui_fork.py b/tests/test_pagure_flask_ui_fork.py
|
||||
index 8e8dce1c..1bff134f 100644
|
||||
--- a/tests/test_pagure_flask_ui_fork.py
|
||||
+++ b/tests/test_pagure_flask_ui_fork.py
|
||||
@@ -4676,10 +4676,7 @@ More information</textarea>
|
||||
# Check fork-edit doesn't show for binary files
|
||||
output = self.app.get("/test/blob/master/f/test.jpg")
|
||||
self.assertEqual(output.status_code, 200)
|
||||
- self.assertNotIn(
|
||||
- "Fork and Edit\n </button>\n",
|
||||
- output.get_data(as_text=True),
|
||||
- )
|
||||
+ self.assertNotIn(b"<html", output.data)
|
||||
|
||||
# Check for edit panel
|
||||
output = self.app.post(
|
||||
@@ -4737,8 +4734,7 @@ More information</textarea>
|
||||
)
|
||||
self.assertEqual(output.status_code, 400)
|
||||
self.assertIn(
|
||||
- "<p>Cannot edit binary files</p>",
|
||||
- output.get_data(as_text=True),
|
||||
+ b"<p>Cannot edit binary files</p>", output.data,
|
||||
)
|
||||
|
||||
# Check fork-edit shows when user is not logged in
|
||||
@@ -4764,10 +4760,7 @@ More information</textarea>
|
||||
# Check fork-edit doesn't show for binary
|
||||
output = self.app.get("/test/blob/master/f/test.jpg")
|
||||
self.assertEqual(output.status_code, 200)
|
||||
- self.assertNotIn(
|
||||
- "Edit in your fork\n </button>\n",
|
||||
- output.get_data(as_text=True),
|
||||
- )
|
||||
+ self.assertNotIn(b"<html", output.data)
|
||||
|
||||
@patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
|
||||
def test_fork_edit_file_namespace(self):
|
||||
@@ -4865,10 +4858,7 @@ More information</textarea>
|
||||
"/somenamespace/test3/blob/master/f/test.jpg"
|
||||
)
|
||||
self.assertEqual(output.status_code, 200)
|
||||
- self.assertNotIn(
|
||||
- "Fork and Edit\n </button>\n",
|
||||
- output.get_data(as_text=True),
|
||||
- )
|
||||
+ self.assertNotIn(b"<html", output.data)
|
||||
|
||||
# Check for edit panel
|
||||
output = self.app.post(
|
||||
diff --git a/tests/test_pagure_flask_ui_repo.py b/tests/test_pagure_flask_ui_repo.py
|
||||
index 27bf6e65..b4322e7d 100644
|
||||
--- a/tests/test_pagure_flask_ui_repo.py
|
||||
+++ b/tests/test_pagure_flask_ui_repo.py
|
||||
@@ -2592,12 +2592,7 @@ class PagureFlaskRepotests(tests.Modeltests):
|
||||
# View what's supposed to be an image
|
||||
output = self.app.get("/test/blob/master/f/test.jpg")
|
||||
self.assertEqual(output.status_code, 200)
|
||||
- output_text = output.get_data(as_text=True)
|
||||
- self.assertIn("Binary files cannot be rendered.<br/>", output_text)
|
||||
- self.assertIn(
|
||||
- '<a href="/test/raw/master/f/test.jpg">view the raw version',
|
||||
- output_text,
|
||||
- )
|
||||
+ self.assertNotIn(b"<html", output.data)
|
||||
|
||||
# View by commit id
|
||||
repo = pygit2.Repository(os.path.join(self.path, "repos", "test.git"))
|
||||
@@ -2605,23 +2600,17 @@ class PagureFlaskRepotests(tests.Modeltests):
|
||||
|
||||
output = self.app.get("/test/blob/%s/f/test.jpg" % commit.oid.hex)
|
||||
self.assertEqual(output.status_code, 200)
|
||||
- output_text = output.get_data(as_text=True)
|
||||
- self.assertIn("Binary files cannot be rendered.<br/>", output_text)
|
||||
- self.assertIn('/f/test.jpg">view the raw version', output_text)
|
||||
+ self.assertNotIn(b"<html", output.data)
|
||||
|
||||
# View by image name -- somehow we support this
|
||||
- output = self.app.get("/test/blob/sources/f/test.jpg")
|
||||
+ output = self.app.get("/test/blob/master/f/test.jpg")
|
||||
self.assertEqual(output.status_code, 200)
|
||||
- output_text = output.get_data(as_text=True)
|
||||
- self.assertIn("Binary files cannot be rendered.<br/>", output_text)
|
||||
- self.assertIn('/f/test.jpg">view the raw version', output_text)
|
||||
+ self.assertNotIn(b"<html", output.data)
|
||||
|
||||
# View binary file
|
||||
- output = self.app.get("/test/blob/sources/f/test_binary")
|
||||
+ output = self.app.get("/test/blob/master/f/test_binary")
|
||||
self.assertEqual(output.status_code, 200)
|
||||
- output_text = output.get_data(as_text=True)
|
||||
- self.assertIn('/f/test_binary">view the raw version', output_text)
|
||||
- self.assertIn("Binary files cannot be rendered.<br/>", output_text)
|
||||
+ self.assertNotIn(b"<html", output.data)
|
||||
|
||||
# View folder
|
||||
output = self.app.get("/test/blob/master/f/folder1")
|
||||
@@ -2748,7 +2737,7 @@ class PagureFlaskRepotests(tests.Modeltests):
|
||||
output = self.app.get("/test/blob/master/f/sources")
|
||||
self.assertEqual(output.status_code, 200)
|
||||
output_text = output.get_data(as_text=True)
|
||||
- self.assertIn("Binary files cannot be rendered.<br/>", output_text)
|
||||
+ self.assertEqual("foo\n bar", output_text)
|
||||
|
||||
def test_view_raw_file(self):
|
||||
""" Test the view_raw_file endpoint. """
|
||||
diff --git a/tests/test_pagure_flask_ui_repo_view_file.py b/tests/test_pagure_flask_ui_repo_view_file.py
|
||||
index 16a1ce18..effa06b6 100644
|
||||
--- a/tests/test_pagure_flask_ui_repo_view_file.py
|
||||
+++ b/tests/test_pagure_flask_ui_repo_view_file.py
|
||||
@@ -135,12 +135,7 @@ class PagureFlaskRepoViewFiletests(LocalBasetests):
|
||||
# View what's supposed to be an image
|
||||
output = self.app.get("/test/blob/master/f/test.jpg")
|
||||
self.assertEqual(output.status_code, 200)
|
||||
- output_text = output.get_data(as_text=True)
|
||||
- self.assertIn("Binary files cannot be rendered.<br/>", output_text)
|
||||
- self.assertIn(
|
||||
- '<a href="/test/raw/master/f/test.jpg">view the raw version',
|
||||
- output_text,
|
||||
- )
|
||||
+ self.assertNotIn(b"<html", output.data)
|
||||
|
||||
def test_view_file_by_commit(self):
|
||||
""" Test the view_file in a specific commit. """
|
||||
@@ -151,29 +146,29 @@ class PagureFlaskRepoViewFiletests(LocalBasetests):
|
||||
|
||||
output = self.app.get("/test/blob/%s/f/test.jpg" % commit.oid.hex)
|
||||
self.assertEqual(output.status_code, 200)
|
||||
- output_text = output.get_data(as_text=True)
|
||||
- self.assertIn("Binary files cannot be rendered.<br/>", output_text)
|
||||
- self.assertIn('/f/test.jpg">view the raw version', output_text)
|
||||
+ self.assertNotIn(b"<html", output.data)
|
||||
|
||||
- def test_view_file_by_name(self):
|
||||
+ def test_view_file_invalid_branch(self):
|
||||
""" Test the view_file via a image name. """
|
||||
-
|
||||
- # View by image name -- somehow we support this
|
||||
output = self.app.get("/test/blob/sources/f/test.jpg")
|
||||
- self.assertEqual(output.status_code, 200)
|
||||
- output_text = output.get_data(as_text=True)
|
||||
- self.assertIn("Binary files cannot be rendered.<br/>", output_text)
|
||||
- self.assertIn('/f/test.jpg">view the raw version', output_text)
|
||||
+ self.assertEqual(output.status_code, 404)
|
||||
|
||||
- def test_view_file_binary_file2(self):
|
||||
+ def test_view_file_invalid_branch2(self):
|
||||
""" Test the view_file with a binary file (2). """
|
||||
-
|
||||
- # View binary file
|
||||
output = self.app.get("/test/blob/sources/f/test_binary")
|
||||
+ self.assertEqual(output.status_code, 404)
|
||||
+
|
||||
+ def test_view_file_invalid_branch(self):
|
||||
+ """ Test the view_file via a image name. """
|
||||
+ output = self.app.get("/test/blob/master/f/test.jpg")
|
||||
self.assertEqual(output.status_code, 200)
|
||||
- output_text = output.get_data(as_text=True)
|
||||
- self.assertIn('/f/test_binary">view the raw version', output_text)
|
||||
- self.assertTrue("Binary files cannot be rendered.<br/>" in output_text)
|
||||
+ self.assertNotIn(b"<html", output.data)
|
||||
+
|
||||
+ def test_view_file_invalid_branch2(self):
|
||||
+ """ Test the view_file with a binary file (2). """
|
||||
+ output = self.app.get("/test/blob/master/f/test_binary")
|
||||
+ self.assertEqual(output.status_code, 200)
|
||||
+ self.assertNotIn(b"<html", output.data)
|
||||
|
||||
def test_view_file_for_folder(self):
|
||||
""" Test the view_file with a folder. """
|
||||
--
|
||||
2.26.2
|
||||
|
86
0007-Remove-fenced-code-block-when-checking-mention.patch
Normal file
86
0007-Remove-fenced-code-block-when-checking-mention.patch
Normal file
@ -0,0 +1,86 @@
|
||||
From e921f23f8135d3e6667d532e06504f520b8c0109 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Scherer <misc@redhat.com>
|
||||
Date: Thu, 3 Sep 2020 16:44:20 +0200
|
||||
Subject: [PATCH 7/9] Remove fenced code block when checking mention
|
||||
|
||||
Fix bug #4978
|
||||
|
||||
We have to remove code using the '~~~~' markup since
|
||||
this result in incorrect trigger, especially on private
|
||||
ticket.
|
||||
---
|
||||
pagure/lib/notify.py | 6 +++++-
|
||||
tests/test_pagure_lib_notify.py | 26 ++++++++++++++++++++++++++
|
||||
2 files changed, 31 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/pagure/lib/notify.py b/pagure/lib/notify.py
|
||||
index 0c124db9..02c277c0 100644
|
||||
--- a/pagure/lib/notify.py
|
||||
+++ b/pagure/lib/notify.py
|
||||
@@ -35,6 +35,7 @@ import pagure.lib.query
|
||||
import pagure.lib.tasks_services
|
||||
from pagure.config import config as pagure_config
|
||||
from pagure.pfmarkdown import MENTION_RE
|
||||
+from markdown.extensions.fenced_code import FencedBlockPreprocessor
|
||||
|
||||
|
||||
_log = logging.getLogger(__name__)
|
||||
@@ -234,7 +235,10 @@ def _add_mentioned_users(emails, comment):
|
||||
""" Check the comment to see if an user is mentioned in it and if
|
||||
so add this user to the list of people to notify.
|
||||
"""
|
||||
- for username in re.findall(MENTION_RE, comment):
|
||||
+ filtered_comment = re.sub(
|
||||
+ FencedBlockPreprocessor.FENCED_BLOCK_RE, "", comment
|
||||
+ )
|
||||
+ for username in re.findall(MENTION_RE, filtered_comment):
|
||||
user = pagure.lib.query.search_user(flask.g.session, username=username)
|
||||
if user:
|
||||
emails.add(user.default_email)
|
||||
diff --git a/tests/test_pagure_lib_notify.py b/tests/test_pagure_lib_notify.py
|
||||
index 8d31cb70..78af57af 100644
|
||||
--- a/tests/test_pagure_lib_notify.py
|
||||
+++ b/tests/test_pagure_lib_notify.py
|
||||
@@ -25,6 +25,7 @@ import pagure.lib.model
|
||||
import pagure.lib.notify
|
||||
import pagure.lib.query
|
||||
import tests
|
||||
+import munch
|
||||
|
||||
|
||||
class PagureLibNotifytests(tests.Modeltests):
|
||||
@@ -543,6 +544,31 @@ RW1haWwgY29udGVudA==
|
||||
"""
|
||||
self.assertEqual(email.as_string(), exp)
|
||||
|
||||
+ def test_notification_mention(self):
|
||||
+ g = munch.Munch()
|
||||
+ g.session = self.session
|
||||
+ with patch("flask.g", g):
|
||||
+
|
||||
+ def _check_mention(comment, exp):
|
||||
+ emails = set([])
|
||||
+ emails = pagure.lib.notify._add_mentioned_users(
|
||||
+ emails, comment
|
||||
+ )
|
||||
+
|
||||
+ self.assertEqual(emails, exp)
|
||||
+
|
||||
+ exp = set(["bar@pingou.com"])
|
||||
+ comment = "I think we should ask @pingou how to pronounce pagure"
|
||||
+ _check_mention(comment, exp)
|
||||
+
|
||||
+ exp = set([])
|
||||
+ comment = """Let me quote him:
|
||||
+~~~~
|
||||
+ @pingou> Pagure is pronounced 'pa-gure', not 'pagu-re'
|
||||
+~~~~
|
||||
+"""
|
||||
+ _check_mention(comment, exp)
|
||||
+
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main(verbosity=2)
|
||||
--
|
||||
2.26.2
|
||||
|
284
0008-Add-support-for-using-cchardet-to-detect-files-encod.patch
Normal file
284
0008-Add-support-for-using-cchardet-to-detect-files-encod.patch
Normal file
@ -0,0 +1,284 @@
|
||||
From a8b2e001d6f4d2e4683aa65d6331b971f8e2ce33 Mon Sep 17 00:00:00 2001
|
||||
From: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||
Date: Mon, 14 Sep 2020 16:03:31 +0200
|
||||
Subject: [PATCH 8/9] Add support for using cchardet to detect files' encoding
|
||||
|
||||
cchardet is a much faster version of the chardet library that can
|
||||
be used to automatically detect the encoding of a file.
|
||||
|
||||
Since this library is only available on python3, we're making it
|
||||
an optional dependency for now.
|
||||
|
||||
Fixes https://pagure.io/pagure/issue/4977
|
||||
|
||||
Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||
---
|
||||
pagure/lib/encoding_utils.py | 12 ++++-
|
||||
tests/test_pagure_flask_ui_repo.py | 58 ++++++++++++++++++++-----
|
||||
tests/test_pagure_lib_encoding_utils.py | 40 ++++++++++++-----
|
||||
tests/test_pagure_lib_mimetype.py | 28 ++++++++++--
|
||||
4 files changed, 111 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/pagure/lib/encoding_utils.py b/pagure/lib/encoding_utils.py
|
||||
index 66f7dced..304e7d84 100644
|
||||
--- a/pagure/lib/encoding_utils.py
|
||||
+++ b/pagure/lib/encoding_utils.py
|
||||
@@ -15,7 +15,12 @@ from __future__ import unicode_literals, division, absolute_import
|
||||
from collections import namedtuple
|
||||
import logging
|
||||
|
||||
-from chardet import universaldetector, __version__ as ch_version
|
||||
+try:
|
||||
+ import cchardet
|
||||
+ from cchardet import __version__ as ch_version
|
||||
+except ImportError:
|
||||
+ cchardet = None
|
||||
+ from chardet import universaldetector, __version__ as ch_version
|
||||
|
||||
from pagure.exceptions import PagureEncodingException
|
||||
|
||||
@@ -44,7 +49,10 @@ def detect_encodings(data):
|
||||
|
||||
# We can't use ``chardet.detect`` because we want to dig in the internals
|
||||
# of the detector to bias the utf-8 result.
|
||||
- detector = universaldetector.UniversalDetector()
|
||||
+ if cchardet is not None:
|
||||
+ detector = cchardet.UniversalDetector()
|
||||
+ else:
|
||||
+ detector = universaldetector.UniversalDetector()
|
||||
detector.reset()
|
||||
detector.feed(data)
|
||||
result = detector.close()
|
||||
diff --git a/tests/test_pagure_flask_ui_repo.py b/tests/test_pagure_flask_ui_repo.py
|
||||
index b4322e7d..e816e7f7 100644
|
||||
--- a/tests/test_pagure_flask_ui_repo.py
|
||||
+++ b/tests/test_pagure_flask_ui_repo.py
|
||||
@@ -20,6 +20,12 @@ import tempfile
|
||||
import time
|
||||
import os
|
||||
|
||||
+cchardet = None
|
||||
+try:
|
||||
+ import cchardet
|
||||
+except ImportError:
|
||||
+ pass
|
||||
+
|
||||
import pygit2
|
||||
import six
|
||||
from mock import ANY, patch, MagicMock
|
||||
@@ -2763,9 +2769,16 @@ class PagureFlaskRepotests(tests.Modeltests):
|
||||
output = self.app.get("/test/raw/master")
|
||||
self.assertEqual(output.status_code, 200)
|
||||
output_text = output.get_data(as_text=True)
|
||||
- self.assertEqual(
|
||||
- output.headers["Content-Type"].lower(), "text/plain; charset=ascii"
|
||||
- )
|
||||
+ if cchardet is not None:
|
||||
+ self.assertEqual(
|
||||
+ output.headers["Content-Type"].lower(),
|
||||
+ "text/plain; charset=utf-8",
|
||||
+ )
|
||||
+ else:
|
||||
+ self.assertEqual(
|
||||
+ output.headers["Content-Type"].lower(),
|
||||
+ "text/plain; charset=ascii",
|
||||
+ )
|
||||
self.assertIn(":Author: Pierre-Yves Chibon", output_text)
|
||||
|
||||
# Add some more content to the repo
|
||||
@@ -2784,9 +2797,16 @@ class PagureFlaskRepotests(tests.Modeltests):
|
||||
|
||||
# View in a branch
|
||||
output = self.app.get("/test/raw/master/f/sources")
|
||||
- self.assertEqual(
|
||||
- output.headers["Content-Type"].lower(), "text/plain; charset=ascii"
|
||||
- )
|
||||
+ if cchardet is not None:
|
||||
+ self.assertEqual(
|
||||
+ output.headers["Content-Type"].lower(),
|
||||
+ "text/plain; charset=utf-8",
|
||||
+ )
|
||||
+ else:
|
||||
+ self.assertEqual(
|
||||
+ output.headers["Content-Type"].lower(),
|
||||
+ "text/plain; charset=ascii",
|
||||
+ )
|
||||
self.assertEqual(output.status_code, 200)
|
||||
output_text = output.get_data(as_text=True)
|
||||
self.assertIn("foo\n bar", output_text)
|
||||
@@ -2837,9 +2857,16 @@ class PagureFlaskRepotests(tests.Modeltests):
|
||||
output = self.app.get("/test/raw/master")
|
||||
self.assertEqual(output.status_code, 200)
|
||||
output_text = output.get_data(as_text=True)
|
||||
- self.assertEqual(
|
||||
- output.headers["Content-Type"].lower(), "text/plain; charset=ascii"
|
||||
- )
|
||||
+ if cchardet is not None:
|
||||
+ self.assertEqual(
|
||||
+ output.headers["Content-Type"].lower(),
|
||||
+ "text/plain; charset=utf-8",
|
||||
+ )
|
||||
+ else:
|
||||
+ self.assertEqual(
|
||||
+ output.headers["Content-Type"].lower(),
|
||||
+ "text/plain; charset=ascii",
|
||||
+ )
|
||||
self.assertTrue(
|
||||
output_text.startswith("diff --git a/test_binary b/test_binary\n")
|
||||
)
|
||||
@@ -2877,9 +2904,16 @@ class PagureFlaskRepotests(tests.Modeltests):
|
||||
output = self.app.get("/fork/pingou/test3/raw/master/f/sources")
|
||||
self.assertEqual(output.status_code, 200)
|
||||
output_text = output.get_data(as_text=True)
|
||||
- self.assertEqual(
|
||||
- output.headers["Content-Type"].lower(), "text/plain; charset=ascii"
|
||||
- )
|
||||
+ if cchardet is not None:
|
||||
+ self.assertEqual(
|
||||
+ output.headers["Content-Type"].lower(),
|
||||
+ "text/plain; charset=utf-8",
|
||||
+ )
|
||||
+ else:
|
||||
+ self.assertEqual(
|
||||
+ output.headers["Content-Type"].lower(),
|
||||
+ "text/plain; charset=ascii",
|
||||
+ )
|
||||
self.assertIn("foo\n bar", output_text)
|
||||
|
||||
def test_view_commit(self):
|
||||
diff --git a/tests/test_pagure_lib_encoding_utils.py b/tests/test_pagure_lib_encoding_utils.py
|
||||
index ccc8825f..aff7d8ba 100644
|
||||
--- a/tests/test_pagure_lib_encoding_utils.py
|
||||
+++ b/tests/test_pagure_lib_encoding_utils.py
|
||||
@@ -5,11 +5,18 @@ Tests for :module:`pagure.lib.encoding_utils`.
|
||||
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
|
||||
-import chardet
|
||||
import os
|
||||
import unittest
|
||||
import sys
|
||||
|
||||
+cchardet = None
|
||||
+try:
|
||||
+ import cchardet
|
||||
+except ImportError:
|
||||
+ pass
|
||||
+
|
||||
+import chardet
|
||||
+
|
||||
sys.path.insert(
|
||||
0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
|
||||
)
|
||||
@@ -24,7 +31,10 @@ class TestGuessEncoding(unittest.TestCase):
|
||||
"""
|
||||
data = "Twas bryllyg, and the slythy toves did gyre and gymble"
|
||||
result = encoding_utils.guess_encoding(data.encode("ascii"))
|
||||
- self.assertEqual(result, "ascii")
|
||||
+ if cchardet is not None:
|
||||
+ self.assertEqual(result, "utf-8")
|
||||
+ else:
|
||||
+ self.assertEqual(result, "ascii")
|
||||
|
||||
def test_guess_encoding_favor_utf_8(self):
|
||||
"""
|
||||
@@ -56,17 +66,24 @@ class TestGuessEncodings(unittest.TestCase):
|
||||
chardet_result = chardet.detect(data)
|
||||
if chardet.__version__[0] == "3":
|
||||
# The first three have different confidence values
|
||||
+ if cchardet is not None:
|
||||
+ expexted_list = ["utf-8"]
|
||||
+ # The last one in the list (which apparently has only one)
|
||||
+ self.assertEqual(result[-1].encoding, "utf-8")
|
||||
+ else:
|
||||
+ expexted_list = ["utf-8", "ISO-8859-9", "ISO-8859-1"]
|
||||
+ # This is the one with the least confidence
|
||||
+ self.assertEqual(result[-1].encoding, "windows-1255")
|
||||
self.assertListEqual(
|
||||
- [encoding.encoding for encoding in result][:3],
|
||||
- ["utf-8", "ISO-8859-9", "ISO-8859-1"],
|
||||
+ [encoding.encoding for encoding in result][:3], expexted_list
|
||||
)
|
||||
- # This is the one with the least confidence
|
||||
- self.assertEqual(result[-1].encoding, "windows-1255")
|
||||
+
|
||||
# The values in the middle of the list all have the same confidence
|
||||
# value and can't be sorted reliably: use sets.
|
||||
- self.assertEqual(
|
||||
- set([encoding.encoding for encoding in result]),
|
||||
- set(
|
||||
+ if cchardet is not None:
|
||||
+ expected_list = sorted(["utf-8"])
|
||||
+ else:
|
||||
+ expected_list = sorted(
|
||||
[
|
||||
"utf-8",
|
||||
"ISO-8859-9",
|
||||
@@ -89,7 +106,10 @@ class TestGuessEncodings(unittest.TestCase):
|
||||
"windows-1251",
|
||||
"windows-1255",
|
||||
]
|
||||
- ),
|
||||
+ )
|
||||
+ self.assertListEqual(
|
||||
+ sorted(set([encoding.encoding for encoding in result])),
|
||||
+ expected_list,
|
||||
)
|
||||
self.assertEqual(chardet_result["encoding"], "ISO-8859-9")
|
||||
else:
|
||||
diff --git a/tests/test_pagure_lib_mimetype.py b/tests/test_pagure_lib_mimetype.py
|
||||
index d5947bee..8c2f4a31 100644
|
||||
--- a/tests/test_pagure_lib_mimetype.py
|
||||
+++ b/tests/test_pagure_lib_mimetype.py
|
||||
@@ -9,6 +9,12 @@ import os
|
||||
import unittest
|
||||
import sys
|
||||
|
||||
+cchardet = None
|
||||
+try:
|
||||
+ import cchardet
|
||||
+except ImportError:
|
||||
+ pass
|
||||
+
|
||||
from pagure.lib import mimetype
|
||||
|
||||
sys.path.insert(
|
||||
@@ -20,8 +26,18 @@ class TestMIMEType(unittest.TestCase):
|
||||
def test_guess_type(self):
|
||||
dataset = [
|
||||
("hello.html", None, "text/html", None),
|
||||
- ("hello.html", b"#!", "text/html", "ascii"),
|
||||
- ("hello", b"#!", "text/plain", "ascii"),
|
||||
+ (
|
||||
+ "hello.html",
|
||||
+ b"#!",
|
||||
+ "text/html",
|
||||
+ "ascii" if cchardet is None else "utf-8",
|
||||
+ ),
|
||||
+ (
|
||||
+ "hello",
|
||||
+ b"#!",
|
||||
+ "text/plain",
|
||||
+ "ascii" if cchardet is None else "utf-8",
|
||||
+ ),
|
||||
("hello.jpg", None, "image/jpeg", None),
|
||||
("hello.jpg", b"#!", "image/jpeg", None),
|
||||
("hello.jpg", b"\0", "image/jpeg", None),
|
||||
@@ -49,7 +65,13 @@ class TestMIMEType(unittest.TestCase):
|
||||
|
||||
def test_get_normal_headers(self):
|
||||
dataset = [
|
||||
- ("hello", b"#!", "text/plain; charset=ascii"),
|
||||
+ (
|
||||
+ "hello",
|
||||
+ b"#!",
|
||||
+ "text/plain; charset=ascii"
|
||||
+ if cchardet is None
|
||||
+ else "text/plain; charset=utf-8",
|
||||
+ ),
|
||||
("hello.jpg", None, "image/jpeg"),
|
||||
("hello.jpg", b"#!", "image/jpeg"),
|
||||
("hello.jpg", b"\0", "image/jpeg"),
|
||||
--
|
||||
2.26.2
|
||||
|
134
0009-Add-support-for-disabling-user-registration.patch
Normal file
134
0009-Add-support-for-disabling-user-registration.patch
Normal file
@ -0,0 +1,134 @@
|
||||
From 8e23c79fb64d4dd4e6f17f809d7e629840f7e91c Mon Sep 17 00:00:00 2001
|
||||
From: Neal Gompa <ngompa13@gmail.com>
|
||||
Date: Thu, 24 Sep 2020 06:40:06 -0400
|
||||
Subject: [PATCH 9/9] Add support for disabling user registration
|
||||
|
||||
For public/private Pagure instances where it is intended to be used
|
||||
by a single user, having the ability to turn off user registration
|
||||
prevents confusion and closes an avenue of potential denial of service
|
||||
attacks.
|
||||
|
||||
Signed-off-by: Neal Gompa <ngompa13@gmail.com>
|
||||
---
|
||||
doc/configuration.rst | 13 +++++++++++++
|
||||
pagure/default_config.py | 3 +++
|
||||
pagure/templates/login/login.html | 2 ++
|
||||
pagure/ui/login.py | 3 +++
|
||||
tests/test_pagure_flask_ui_login.py | 24 ++++++++++++++++++++++++
|
||||
5 files changed, 45 insertions(+)
|
||||
|
||||
diff --git a/doc/configuration.rst b/doc/configuration.rst
|
||||
index 735e378c..2ea7a66d 100644
|
||||
--- a/doc/configuration.rst
|
||||
+++ b/doc/configuration.rst
|
||||
@@ -1117,6 +1117,7 @@ Valid options are ``fas``, ``openid``, ``oidc``, or ``local``.
|
||||
the configuration options starting with ``OIDC_`` (see below) to be provided.
|
||||
|
||||
* ``local`` causes pagure to use the local pagure database for user management.
|
||||
+ User registration can be disabled with the ALLOW_USER_REGISTRATION configuration key.
|
||||
|
||||
Defaults to: ``local``.
|
||||
|
||||
@@ -1784,6 +1785,18 @@ If turned off, users are managed outside of pagure.
|
||||
Defaults to: ``True``
|
||||
|
||||
|
||||
+ALLOW_USER_REGISTRATION
|
||||
+~~~~~~~~~~~~~~~~~~~~~~~
|
||||
+
|
||||
+This configuration key can be used to turn on or off user registration
|
||||
+(that is, the ability for users to create an account) in this pagure instance.
|
||||
+If turned off, user accounts cannot be created through the UI or API.
|
||||
+Currently, this key only applies to pagure instances configured with the ``local``
|
||||
+authentication backend and has no effect with the other authentication backends.
|
||||
+
|
||||
+Defaults to: ``True``
|
||||
+
|
||||
+
|
||||
SESSION_COOKIE_NAME
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
diff --git a/pagure/default_config.py b/pagure/default_config.py
|
||||
index 045f2704..df0cd6b0 100644
|
||||
--- a/pagure/default_config.py
|
||||
+++ b/pagure/default_config.py
|
||||
@@ -78,6 +78,9 @@ ENABLE_GROUP_MNGT = True
|
||||
# Enables / Disables private projects
|
||||
PRIVATE_PROJECTS = True
|
||||
|
||||
+# Enable / Disable user registration (local auth only)
|
||||
+ALLOW_USER_REGISTRATION = True
|
||||
+
|
||||
# Enable / Disable deleting branches in the UI
|
||||
ALLOW_DELETE_BRANCH = True
|
||||
|
||||
diff --git a/pagure/templates/login/login.html b/pagure/templates/login/login.html
|
||||
index a65b10ae..e209c400 100644
|
||||
--- a/pagure/templates/login/login.html
|
||||
+++ b/pagure/templates/login/login.html
|
||||
@@ -18,11 +18,13 @@
|
||||
<input class="btn btn-primary btn-block mt-4" type="submit" value="Login">
|
||||
{{ form.csrf_token }}
|
||||
</form>
|
||||
+ {% if config.get('ALLOW_USER_REGISTRATION', True) %}
|
||||
<div>
|
||||
<a class="btn btn-link btn-block" href="{{url_for('ui_ns.new_user') }}">
|
||||
Create a new account
|
||||
</a>
|
||||
</div>
|
||||
+ {% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
diff --git a/pagure/ui/login.py b/pagure/ui/login.py
|
||||
index 1a0dbd24..7da94a37 100644
|
||||
--- a/pagure/ui/login.py
|
||||
+++ b/pagure/ui/login.py
|
||||
@@ -38,6 +38,9 @@ _log = logging.getLogger(__name__)
|
||||
def new_user():
|
||||
""" Create a new user.
|
||||
"""
|
||||
+ if not pagure.config.config.get("ALLOW_USER_REGISTRATION", True):
|
||||
+ flask.flash("User registration is disabled.", "error")
|
||||
+ return flask.redirect(flask.url_for("auth_login"))
|
||||
form = forms.NewUserForm()
|
||||
if form.validate_on_submit():
|
||||
|
||||
diff --git a/tests/test_pagure_flask_ui_login.py b/tests/test_pagure_flask_ui_login.py
|
||||
index f11a2b22..8a1d16c7 100644
|
||||
--- a/tests/test_pagure_flask_ui_login.py
|
||||
+++ b/tests/test_pagure_flask_ui_login.py
|
||||
@@ -149,6 +149,30 @@ class PagureFlaskLogintests(tests.SimplePagureTest):
|
||||
items = pagure.lib.query.search_user(self.session)
|
||||
self.assertEqual(3, len(items))
|
||||
|
||||
+ @patch.dict("pagure.config.config", {"PAGURE_AUTH": "local"})
|
||||
+ @patch.dict("pagure.config.config", {"ALLOW_USER_REGISTRATION": False})
|
||||
+ @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
|
||||
+ def test_new_user_disabled(self):
|
||||
+ """ Test the disabling of the new_user endpoint. """
|
||||
+
|
||||
+ # Check before:
|
||||
+ items = pagure.lib.query.search_user(self.session)
|
||||
+ self.assertEqual(2, len(items))
|
||||
+
|
||||
+ # Attempt to access the new user page
|
||||
+ output = self.app.get("/user/new", follow_redirects=True)
|
||||
+ self.assertEqual(output.status_code, 200)
|
||||
+ self.assertIn(
|
||||
+ "<title>Login - Pagure</title>", output.get_data(as_text=True)
|
||||
+ )
|
||||
+ self.assertIn(
|
||||
+ "User registration is disabled.", output.get_data(as_text=True)
|
||||
+ )
|
||||
+
|
||||
+ # Check after:
|
||||
+ items = pagure.lib.query.search_user(self.session)
|
||||
+ self.assertEqual(2, len(items))
|
||||
+
|
||||
@patch.dict("pagure.config.config", {"PAGURE_AUTH": "local"})
|
||||
@patch.dict("pagure.config.config", {"CHECK_SESSION_IP": False})
|
||||
def test_do_login(self):
|
||||
--
|
||||
2.26.2
|
||||
|
@ -1,3 +1,18 @@
|
||||
-------------------------------------------------------------------
|
||||
Thu Sep 24 22:57:42 UTC 2020 - Neal Gompa <ngompa13@gmail.com>
|
||||
|
||||
- Backport various fixes from upstream
|
||||
+ Patch: 0001-Display-real-line-numbers-on-pull-request-s-diff-vie.patch
|
||||
+ Patch: 0002-Show-the-assignee-s-avatar-on-the-board.patch
|
||||
+ Patch: 0003-Allow-setting-a-status-as-closing-even-if-the-projec.patch
|
||||
+ Patch: 0004-Include-the-assignee-in-the-list-of-people-notified-.patch
|
||||
+ Patch: 0005-Introduce-the-collaborator_project_groups-mapping.patch
|
||||
+ Patch: 0006-When-a-file-a-detected-as-a-binary-file-return-the-r.patch
|
||||
+ Patch: 0007-Remove-fenced-code-block-when-checking-mention.patch
|
||||
+ Patch: 0008-Add-support-for-using-cchardet-to-detect-files-encod.patch
|
||||
+ Patch: 0009-Add-support-for-disabling-user-registration.patch
|
||||
- Remove mandatory dependency on systemd to ease containerization
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Sun Aug 30 14:25:21 UTC 2020 - Neal Gompa <ngompa13@gmail.com>
|
||||
|
||||
|
17
pagure.spec
17
pagure.spec
@ -41,6 +41,18 @@ Source1: https://raw.githubusercontent.com/fedora-infra/python-fedora
|
||||
Source10: pagure-README.SUSE
|
||||
|
||||
|
||||
# Backports from upstream
|
||||
Patch0001: 0001-Display-real-line-numbers-on-pull-request-s-diff-vie.patch
|
||||
Patch0002: 0002-Show-the-assignee-s-avatar-on-the-board.patch
|
||||
Patch0003: 0003-Allow-setting-a-status-as-closing-even-if-the-projec.patch
|
||||
Patch0004: 0004-Include-the-assignee-in-the-list-of-people-notified-.patch
|
||||
Patch0005: 0005-Introduce-the-collaborator_project_groups-mapping.patch
|
||||
Patch0006: 0006-When-a-file-a-detected-as-a-binary-file-return-the-r.patch
|
||||
Patch0007: 0007-Remove-fenced-code-block-when-checking-mention.patch
|
||||
Patch0008: 0008-Add-support-for-using-cchardet-to-detect-files-encod.patch
|
||||
Patch0009: 0009-Add-support-for-disabling-user-registration.patch
|
||||
|
||||
|
||||
# SUSE-specific fixes
|
||||
## Change the defaults in the example config to match packaging
|
||||
Patch1000: pagure-5.0-default-example-cfg.patch
|
||||
@ -122,6 +134,9 @@ Requires: python3-dbm
|
||||
Requires: python3-kitchen
|
||||
Requires: python3-requests
|
||||
|
||||
# We want to use cchardet whenever it's available
|
||||
Recommends: python3-cchardet
|
||||
|
||||
# If using PostgreSQL, the correct driver should be installed
|
||||
Recommends: (python3-psycopg2 if postgresql-server)
|
||||
|
||||
@ -137,7 +152,7 @@ Recommends: (%{name}-web-nginx if nginx)
|
||||
# The default theme is required
|
||||
Requires: %{name}-theme-default
|
||||
|
||||
%{?systemd_requires}
|
||||
%{?systemd_ordering}
|
||||
|
||||
# We use the git tools for some actions due to deficiencies in libgit2 and pygit2
|
||||
Requires: git-core
|
||||
|
Loading…
x
Reference in New Issue
Block a user