From ee3e0e5889949870dc401a17812f2030b6caed4a Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jun 11 2015 18:36:01 +0000 Subject: [PATCH 1/16] Strip the ssh keys when writing them to the authorized_keys file This will clean up keys that have a trailing \r in the database. --- diff --git a/pagure/__init__.py b/pagure/__init__.py index 09f4e52..0e7d786 100644 --- a/pagure/__init__.py +++ b/pagure/__init__.py @@ -205,13 +205,14 @@ def generate_authorized_key_file(): # pragma: no cover row = 'command="/usr/bin/gl-auth-command %s",' \ 'no-port-forwarding,no-X11-forwarding,'\ 'no-agent-forwarding,no-pty %s' % ( - user.user, user.public_ssh_key) + user.user, user.public_ssh_key.strip()) elif gitolite_version == 3: row = 'command="HOME=%s '\ '/usr/share/gitolite3/gitolite-shell %s",' \ 'no-port-forwarding,no-X11-forwarding,'\ 'no-agent-forwarding,no-pty %s' % ( - gitolite_home, user.user, user.public_ssh_key) + gitolite_home, user.user, + user.public_ssh_key.strip()) else: raise pagure.exceptions.PagureException( 'Non-supported gitolite version "%s"' % From b5c4d91e55f04c593392f3001fe38ec98479e271 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jun 12 2015 08:14:04 +0000 Subject: [PATCH 2/16] Disable javascript in all the markdown fields --- diff --git a/pagure/ui/filters.py b/pagure/ui/filters.py index 8ee1735..6c03e52 100644 --- a/pagure/ui/filters.py +++ b/pagure/ui/filters.py @@ -224,7 +224,7 @@ def markdown_filter(text): if indent: line = ' %s' % line ntext.append(line) - return markdown.markdown('\n'.join(ntext)) + return no_js(markdown.markdown('\n'.join(ntext))) return '' From 82d3191bdf8faa9e287b0b632bee150e90cbd264 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jun 12 2015 08:27:33 +0000 Subject: [PATCH 3/16] Drop duplicated fields already retrieved by inheritance --- diff --git a/pagure/forms.py b/pagure/forms.py index 9122529..6125451 100644 --- a/pagure/forms.py +++ b/pagure/forms.py @@ -55,23 +55,11 @@ class IssueFormSimplied(wtf.Form): class IssueForm(IssueFormSimplied): ''' Form to create or edit an issue. ''' - title = wtforms.TextField( - 'Title*', - [wtforms.validators.Required()] - ) - issue_content = wtforms.TextAreaField( - 'Content*', - [wtforms.validators.Required()] - ) status = wtforms.SelectField( 'Status', [wtforms.validators.Required()], choices=[(item, item) for item in []] ) - private = wtforms.BooleanField( - 'Private', - [wtforms.validators.optional()], - ) def __init__(self, *args, **kwargs): """ Calls the default constructor with the normal argument but From 845e29a17839980733a89612b924af4ca5cfa4d8 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jun 12 2015 08:28:44 +0000 Subject: [PATCH 4/16] Validate early the input submitted in the forms --- diff --git a/pagure/forms.py b/pagure/forms.py index 6125451..29635e4 100644 --- a/pagure/forms.py +++ b/pagure/forms.py @@ -8,6 +8,7 @@ """ +import re from flask.ext import wtf import wtforms # pylint: disable=R0903,W0232,E1002 @@ -33,7 +34,10 @@ class ProjectForm(ProjectFormSimplified): ''' Form to create or edit project. ''' name = wtforms.TextField( 'Project name *', - [wtforms.validators.Required()] + [ + wtforms.validators.Required(), + wtforms.validators.Regexp('^[^\n:<>]+$', flags=re.IGNORECASE) + ] ) @@ -41,7 +45,10 @@ class IssueFormSimplied(wtf.Form): ''' Form to create or edit an issue. ''' title = wtforms.TextField( 'Title*', - [wtforms.validators.Required()] + [ + wtforms.validators.Required(), + wtforms.validators.Regexp('^[^\n:<>]+$', flags=re.IGNORECASE) + ] ) issue_content = wtforms.TextAreaField( 'Content*', @@ -77,14 +84,21 @@ class RequestPullForm(wtf.Form): ''' Form to create a request pull. ''' title = wtforms.TextField( 'Title*', - [wtforms.validators.Required()] + [ + wtforms.validators.Required(), + wtforms.validators.Regexp('^[^\n:<>]+$', flags=re.IGNORECASE) + ] ) class AddIssueTagForm(wtf.Form): ''' Form to add a comment to an issue. ''' tag = wtforms.TextField( - 'tag', [wtforms.validators.Optional()] + 'tag', + [ + wtforms.validators.Optional(), + wtforms.validators.Regexp('^[^\n:<>]+$', flags=re.IGNORECASE) + ] ) @@ -131,7 +145,11 @@ class NewTokenForm(wtf.Form): class UpdateIssueForm(wtf.Form): ''' Form to add a comment to an issue. ''' tag = wtforms.TextField( - 'tag', [wtforms.validators.Optional()] + 'tag', + [ + wtforms.validators.Optional(), + wtforms.validators.Regexp('^[^\n:<>]+$', flags=re.IGNORECASE) + ] ) depends = wtforms.TextField( 'dependency issue', [wtforms.validators.Optional()] @@ -209,7 +227,10 @@ class AddGroupForm(wtf.Form): ''' Form to add a group to a project. ''' group = wtforms.TextField( 'Group *', - [wtforms.validators.Required()] + [ + wtforms.validators.Required(), + wtforms.validators.Regexp('^[^\n:<>]+$', flags=re.IGNORECASE) + ] ) @@ -255,7 +276,11 @@ class NewGroupForm(wtf.Form): """ Form to ask for a password change. """ group_name = wtforms.TextField( 'Group name *', - [wtforms.validators.Required(), wtforms.validators.Length(max=16)] + [ + wtforms.validators.Required(), + wtforms.validators.Length(max=16), + wtforms.validators.Regexp('^[^\n:<>]+$', flags=re.IGNORECASE) + ] ) group_type = wtforms.SelectField( 'Group type', From ced1fcd2a0ebe09e6c82b3f9215994ff4b99ff01 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jun 12 2015 08:34:15 +0000 Subject: [PATCH 5/16] If the session timed-out, redirect to the setting page after authentication This will avoid the 405 errors after re-authenticating --- diff --git a/pagure/ui/repo.py b/pagure/ui/repo.py index cb2180b..a3d2e9c 100644 --- a/pagure/ui/repo.py +++ b/pagure/ui/repo.py @@ -764,6 +764,13 @@ def view_settings(repo, username=None): def update_project(repo, username=None): """ Update the description of a project. """ + if admin_session_timedout(): + flask.flash('Action canceled, try it again', 'error') + url = flask.url_for( + 'view_settings', username=username, repo=repo.name) + return flask.redirect( + flask.url_for('auth_login', next=url)) + repo = pagure.lib.get_project(SESSION, repo, user=username) if not repo: @@ -799,8 +806,11 @@ def delete_repo(repo, username=None): """ Delete the present project. """ if admin_session_timedout(): + flask.flash('Action canceled, try it again', 'error') + url = flask.url_for( + 'view_settings', username=username, repo=repo.name) return flask.redirect( - flask.url_for('auth_login', next=flask.request.url)) + flask.url_for('auth_login', next=url)) repo = pagure.lib.get_project(SESSION, repo, user=username) @@ -853,8 +863,11 @@ def new_repo_hook_token(repo, username=None): """ Re-generate a hook token for the present project. """ if admin_session_timedout(): + flask.flash('Action canceled, try it again', 'error') + url = flask.url_for( + 'view_settings', username=username, repo=repo.name) return flask.redirect( - flask.url_for('auth_login', next=flask.request.url)) + flask.url_for('auth_login', next=url)) repo = pagure.lib.get_project(SESSION, repo, user=username) @@ -890,8 +903,11 @@ def remove_user(repo, userid, username=None): """ Remove the specified user from the project. """ if admin_session_timedout(): + flask.flash('Action canceled, try it again', 'error') + url = flask.url_for( + 'view_settings', username=username, repo=repo.name) return flask.redirect( - flask.url_for('auth_login', next=flask.request.url)) + flask.url_for('auth_login', next=url)) repo = pagure.lib.get_project(SESSION, repo, user=username) @@ -1048,8 +1064,11 @@ def regenerate_git(repo, username=None): """ Regenerate the specified git repo with the content in the project. """ if admin_session_timedout(): + flask.flash('Action canceled, try it again', 'error') + url = flask.url_for( + 'view_settings', username=username, repo=repo.name) return flask.redirect( - flask.url_for('auth_login', next=flask.request.url)) + flask.url_for('auth_login', next=url)) repo = pagure.lib.get_project(SESSION, repo, user=username) @@ -1147,8 +1166,11 @@ def revoke_api_token(repo, token_id, username=None): """ Revokie a token to a specified project. """ if admin_session_timedout(): + flask.flash('Action canceled, try it again', 'error') + url = flask.url_for( + 'view_settings', username=username, repo=repo.name) return flask.redirect( - flask.url_for('auth_login', next=flask.request.url)) + flask.url_for('auth_login', next=url)) repo = pagure.lib.get_project(SESSION, repo, user=username) From e266f00b10b6e8f26224fb457d35ca8b0be4f21c Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jun 12 2015 08:37:04 +0000 Subject: [PATCH 6/16] Inform the user that if the session timed-out, the action got canceled This might avoid confusion if the session times out between the GET and the POST requests. --- diff --git a/pagure/ui/repo.py b/pagure/ui/repo.py index a3d2e9c..53e9b3e 100644 --- a/pagure/ui/repo.py +++ b/pagure/ui/repo.py @@ -704,6 +704,8 @@ def view_settings(repo, username=None): """ Presents the settings of the project. """ if admin_session_timedout(): + if flask.request.method == 'POST': + flask.flash('Action canceled, try it again', 'error') return flask.redirect( flask.url_for('auth_login', next=flask.request.url)) @@ -958,6 +960,8 @@ def add_user(repo, username=None): """ Add the specified user from the project. """ if admin_session_timedout(): + if flask.request.method == 'POST': + flask.flash('Action canceled, try it again', 'error') return flask.redirect( flask.url_for('auth_login', next=flask.request.url)) @@ -1012,6 +1016,8 @@ def add_group_project(repo, username=None): """ Add the specified group from the project. """ if admin_session_timedout(): + if flask.request.method == 'POST': + flask.flash('Action canceled, try it again', 'error') return flask.redirect( flask.url_for('auth_login', next=flask.request.url)) @@ -1114,6 +1120,8 @@ def add_token(repo, username=None): """ Add a token to a specified project. """ if admin_session_timedout(): + if flask.request.method == 'POST': + flask.flash('Action canceled, try it again', 'error') return flask.redirect( flask.url_for('auth_login', next=flask.request.url)) From 484ff9f05ae9b124733611ddd2c8fac3e18986ae Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jun 12 2015 08:40:49 +0000 Subject: [PATCH 7/16] Fix typos, we're at the time where we do not have the repo object, just its name --- diff --git a/pagure/ui/repo.py b/pagure/ui/repo.py index 53e9b3e..a5441e5 100644 --- a/pagure/ui/repo.py +++ b/pagure/ui/repo.py @@ -810,7 +810,7 @@ def delete_repo(repo, username=None): if admin_session_timedout(): flask.flash('Action canceled, try it again', 'error') url = flask.url_for( - 'view_settings', username=username, repo=repo.name) + 'view_settings', username=username, repo=repo) return flask.redirect( flask.url_for('auth_login', next=url)) @@ -867,7 +867,7 @@ def new_repo_hook_token(repo, username=None): if admin_session_timedout(): flask.flash('Action canceled, try it again', 'error') url = flask.url_for( - 'view_settings', username=username, repo=repo.name) + 'view_settings', username=username, repo=repo) return flask.redirect( flask.url_for('auth_login', next=url)) @@ -907,7 +907,7 @@ def remove_user(repo, userid, username=None): if admin_session_timedout(): flask.flash('Action canceled, try it again', 'error') url = flask.url_for( - 'view_settings', username=username, repo=repo.name) + 'view_settings', username=username, repo=repo) return flask.redirect( flask.url_for('auth_login', next=url)) @@ -1072,7 +1072,7 @@ def regenerate_git(repo, username=None): if admin_session_timedout(): flask.flash('Action canceled, try it again', 'error') url = flask.url_for( - 'view_settings', username=username, repo=repo.name) + 'view_settings', username=username, repo=repo) return flask.redirect( flask.url_for('auth_login', next=url)) @@ -1176,7 +1176,7 @@ def revoke_api_token(repo, token_id, username=None): if admin_session_timedout(): flask.flash('Action canceled, try it again', 'error') url = flask.url_for( - 'view_settings', username=username, repo=repo.name) + 'view_settings', username=username, repo=repo) return flask.redirect( flask.url_for('auth_login', next=url)) From 2ac7dffe8761106cfb406c867c023263bbd19354 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jun 12 2015 08:42:11 +0000 Subject: [PATCH 8/16] Catch PagureException when adjusting the project's settings This exception can be due to the web-hook failing --- diff --git a/pagure/ui/repo.py b/pagure/ui/repo.py index a5441e5..b5ea443 100644 --- a/pagure/ui/repo.py +++ b/pagure/ui/repo.py @@ -744,6 +744,9 @@ def view_settings(repo, username=None): flask.flash(message) return flask.redirect(flask.url_for( 'view_repo', username=username, repo=repo.name)) + except pagure.exceptions.PagureException as msg: + SESSION.rollback() + flask.flash(msg, 'error') except SQLAlchemyError, err: # pragma: no cover SESSION.rollback() flask.flash(str(err), 'error') From d2002ed4674b9719311c526a5161a0fffa61d1cc Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jun 12 2015 13:42:46 +0000 Subject: [PATCH 9/16] Use an inclusive regex instead of exclusive and make it a global variable --- diff --git a/pagure/forms.py b/pagure/forms.py index 29635e4..552fe9c 100644 --- a/pagure/forms.py +++ b/pagure/forms.py @@ -14,6 +14,9 @@ import wtforms # pylint: disable=R0903,W0232,E1002 +REGEX = '^[a-zA-Z0-9]+$' + + class ProjectFormSimplified(wtf.Form): ''' Form to edit the description of a project. ''' description = wtforms.TextField( @@ -36,7 +39,7 @@ class ProjectForm(ProjectFormSimplified): 'Project name *', [ wtforms.validators.Required(), - wtforms.validators.Regexp('^[^\n:<>]+$', flags=re.IGNORECASE) + wtforms.validators.Regexp(REGEX, flags=re.IGNORECASE) ] ) @@ -47,7 +50,7 @@ class IssueFormSimplied(wtf.Form): 'Title*', [ wtforms.validators.Required(), - wtforms.validators.Regexp('^[^\n:<>]+$', flags=re.IGNORECASE) + wtforms.validators.Regexp(REGEX, flags=re.IGNORECASE) ] ) issue_content = wtforms.TextAreaField( @@ -86,7 +89,7 @@ class RequestPullForm(wtf.Form): 'Title*', [ wtforms.validators.Required(), - wtforms.validators.Regexp('^[^\n:<>]+$', flags=re.IGNORECASE) + wtforms.validators.Regexp(REGEX, flags=re.IGNORECASE) ] ) @@ -97,7 +100,7 @@ class AddIssueTagForm(wtf.Form): 'tag', [ wtforms.validators.Optional(), - wtforms.validators.Regexp('^[^\n:<>]+$', flags=re.IGNORECASE) + wtforms.validators.Regexp(REGEX, flags=re.IGNORECASE) ] ) @@ -148,7 +151,7 @@ class UpdateIssueForm(wtf.Form): 'tag', [ wtforms.validators.Optional(), - wtforms.validators.Regexp('^[^\n:<>]+$', flags=re.IGNORECASE) + wtforms.validators.Regexp(REGEX, flags=re.IGNORECASE) ] ) depends = wtforms.TextField( @@ -229,7 +232,7 @@ class AddGroupForm(wtf.Form): 'Group *', [ wtforms.validators.Required(), - wtforms.validators.Regexp('^[^\n:<>]+$', flags=re.IGNORECASE) + wtforms.validators.Regexp(REGEX, flags=re.IGNORECASE) ] ) @@ -279,7 +282,7 @@ class NewGroupForm(wtf.Form): [ wtforms.validators.Required(), wtforms.validators.Length(max=16), - wtforms.validators.Regexp('^[^\n:<>]+$', flags=re.IGNORECASE) + wtforms.validators.Regexp(REGEX, flags=re.IGNORECASE) ] ) group_type = wtforms.SelectField( From 1ff9936733bef31a9a20e0a75d9c6ec7899669be Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jun 12 2015 13:52:04 +0000 Subject: [PATCH 10/16] Redirect the /api endpoint to the api documentation place --- diff --git a/pagure/api/__init__.py b/pagure/api/__init__.py index 49b4d83..0448ab1 100644 --- a/pagure/api/__init__.py +++ b/pagure/api/__init__.py @@ -400,3 +400,12 @@ def api(): api_error_codes_doc, ], ) + + +@APP.route('/api/') +@APP.route('/api') +def api_redirect(): + ''' Redirects the user to the API documentation page. + + ''' + return flask.redirect(flask.url_for('api_ns.api')) From 456793fa234dfbc6e86252c4a5a2d6fe7b1adc0e Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jun 12 2015 14:02:59 +0000 Subject: [PATCH 11/16] Make a more flexible regex as some entries can contain spaces or some characters --- diff --git a/pagure/forms.py b/pagure/forms.py index 552fe9c..637445e 100644 --- a/pagure/forms.py +++ b/pagure/forms.py @@ -14,7 +14,8 @@ import wtforms # pylint: disable=R0903,W0232,E1002 -REGEX = '^[a-zA-Z0-9]+$' +REGEX = '^[a-zA-Z0-9-_]+$' +REGEX2 = '^[a-zA-Z0-9 ]+$' class ProjectFormSimplified(wtf.Form): @@ -50,7 +51,7 @@ class IssueFormSimplied(wtf.Form): 'Title*', [ wtforms.validators.Required(), - wtforms.validators.Regexp(REGEX, flags=re.IGNORECASE) + wtforms.validators.Regexp(REGEX2, flags=re.IGNORECASE) ] ) issue_content = wtforms.TextAreaField( @@ -89,7 +90,7 @@ class RequestPullForm(wtf.Form): 'Title*', [ wtforms.validators.Required(), - wtforms.validators.Regexp(REGEX, flags=re.IGNORECASE) + wtforms.validators.Regexp(REGEX2, flags=re.IGNORECASE) ] ) From a45db88ede50b8bdee729e0f035b3a2f248721b5 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jun 12 2015 14:06:45 +0000 Subject: [PATCH 12/16] Allow the '#' in the more relax fields --- diff --git a/pagure/forms.py b/pagure/forms.py index 637445e..56b530e 100644 --- a/pagure/forms.py +++ b/pagure/forms.py @@ -15,7 +15,7 @@ import wtforms REGEX = '^[a-zA-Z0-9-_]+$' -REGEX2 = '^[a-zA-Z0-9 ]+$' +REGEX2 = '^[a-zA-Z0-9 #]+$' class ProjectFormSimplified(wtf.Form): From b53d8cdf67afa7fa5865b6e3e72f587e99e90778 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jun 12 2015 14:07:04 +0000 Subject: [PATCH 13/16] Adjust the unit-tests for the stricter checking of the input made in the forms --- diff --git a/tests/test_progit_flask_ui_app.py b/tests/test_progit_flask_ui_app.py index d7b2d28..cdaf071 100644 --- a/tests/test_progit_flask_ui_app.py +++ b/tests/test_progit_flask_ui_app.py @@ -154,7 +154,7 @@ class PagureFlaskApptests(tests.Modeltests): 'This field is required.' in output.data) - data['name'] = 'project#1' + data['name'] = 'project-1' output = self.app.post('/new/', data=data) self.assertEqual(output.status_code, 200) self.assertTrue('

New project

' in output.data) @@ -177,20 +177,20 @@ class PagureFlaskApptests(tests.Modeltests): self.assertEqual(output.status_code, 200) self.assertTrue('

Project #1

' in output.data) self.assertTrue( - '
  • Project "project#1" created
  • ' + '
  • Project "project-1" created
  • ' in output.data) # After projects = pagure.lib.search_projects(self.session) self.assertEqual(len(projects), 1) self.assertTrue(os.path.exists( - os.path.join(tests.HERE, 'project#1.git'))) + os.path.join(tests.HERE, 'project-1.git'))) self.assertTrue(os.path.exists( - os.path.join(tests.HERE, 'tickets', 'project#1.git'))) + os.path.join(tests.HERE, 'tickets', 'project-1.git'))) self.assertTrue(os.path.exists( - os.path.join(tests.HERE, 'docs', 'project#1.git'))) + os.path.join(tests.HERE, 'docs', 'project-1.git'))) self.assertTrue(os.path.exists( - os.path.join(tests.HERE, 'requests', 'project#1.git'))) + os.path.join(tests.HERE, 'requests', 'project-1.git'))) @patch('pagure.ui.app.admin_session_timedout') def test_user_settings(self, ast): diff --git a/tests/test_progit_flask_ui_groups.py b/tests/test_progit_flask_ui_groups.py index c04a1cb..dd749ff 100644 --- a/tests/test_progit_flask_ui_groups.py +++ b/tests/test_progit_flask_ui_groups.py @@ -88,7 +88,7 @@ class PagureFlaskGroupstests(tests.Modeltests): 'This field is required.'), 1) data = { - 'group_name': 'test group', + 'group_name': 'test_group', } # Missing CSRF @@ -100,17 +100,7 @@ class PagureFlaskGroupstests(tests.Modeltests): data['csrf_token'] = csrf_token - # Space in the group - output = self.app.post( - '/group/add', data=data) - self.assertEqual(output.status_code, 200) - self.assertIn('

    Create group

    ', output.data) - self.assertIn( - '
  • Spaces are not allowed in group names: ' - 'test group
  • ' , output.data) - # All good - data['group_name'] = 'test_group' output = self.app.post( '/group/add', data=data, follow_redirects=True) self.assertEqual(output.status_code, 200) diff --git a/tests/test_progit_flask_ui_issues.py b/tests/test_progit_flask_ui_issues.py index c0001ec..a34c61c 100644 --- a/tests/test_progit_flask_ui_issues.py +++ b/tests/test_progit_flask_ui_issues.py @@ -486,7 +486,7 @@ class PagureFlaskIssuestests(tests.Modeltests): data = { 'csrf_token': csrf_token, 'status': 'Fixed', - 'tag': 'tag#2', + 'tag': 'tag2', } output = self.app.post( '/test/issue/1/update', data=data, follow_redirects=True) @@ -495,7 +495,7 @@ class PagureFlaskIssuestests(tests.Modeltests): '

    test project #1

    ' in output.data) self.assertTrue( - '
  • Tag added: tag#2
  • ' in output.data) + '
  • Tag added: tag2
  • ' in output.data) self.assertFalse( 'li class="message">No changes to edit' in output.data) self.assertTrue( From 257353370b2d888181c2763552b21324dfa9e5cb Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jun 12 2015 14:26:51 +0000 Subject: [PATCH 14/16] Fix how is retrieved the list of emails to send the notification to --- diff --git a/pagure/lib/notify.py b/pagure/lib/notify.py index b3b8739..c6ac4d1 100644 --- a/pagure/lib/notify.py +++ b/pagure/lib/notify.py @@ -372,11 +372,7 @@ To reply, visit the link below or just reply to this email request.project.name, 'pull-request', request.id)) - mail_to = set([cmt.user.default_email for cmt in request.comments]) - mail_to.add(request.project.user.default_email) - for prouser in request.project.users: - if prouser.default_email: - mail_to.add(prouser.default_email) + mail_to = _get_emails_for_issue(request) send_email( text, @@ -408,11 +404,7 @@ Merged pull-request: request.project.name, 'pull-request', request.id)) - mail_to = set([cmt.user.default_email for cmt in request.comments]) - mail_to.add(request.project.user.default_email) - for prouser in request.project.users: - if prouser.default_email: - mail_to.add(prouser.default_email) + mail_to = _get_emails_for_issue(request) uid = time.mktime(datetime.datetime.now().timetuple()) send_email( @@ -446,11 +438,7 @@ Cancelled pull-request: request.project.name, 'pull-request', request.id)) - mail_to = set([cmt.user.default_email for cmt in request.comments]) - mail_to.add(request.project.user.default_email) - for prouser in request.project.users: - if prouser.default_email: - mail_to.add(prouser.default_email) + mail_to = _get_emails_for_issue(request) uid = time.mktime(datetime.datetime.now().timetuple()) send_email( @@ -482,14 +470,7 @@ To reply, visit the link below or just reply to this email comment.pull_request.project.name, 'pull-request', comment.pull_request.id)) - mail_to = set([ - cmt.user.default_email - for cmt in comment.pull_request.comments]) - mail_to.add(comment.pull_request.project.user.default_email) - for prouser in comment.pull_request.project.users: - if prouser.default_email: - mail_to.add(prouser.default_email) - + mail_to = _get_emails_for_issue(request) mail_to = _clean_emails(mail_to, user) send_email( From 2fe2965befe85afd6a616c6750ef61341de7a5b6 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jun 12 2015 14:39:58 +0000 Subject: [PATCH 15/16] Fix typo --- diff --git a/pagure/lib/notify.py b/pagure/lib/notify.py index c6ac4d1..6a15fe5 100644 --- a/pagure/lib/notify.py +++ b/pagure/lib/notify.py @@ -470,7 +470,7 @@ To reply, visit the link below or just reply to this email comment.pull_request.project.name, 'pull-request', comment.pull_request.id)) - mail_to = _get_emails_for_issue(request) + mail_to = _get_emails_for_issue(comment.pull_request) mail_to = _clean_emails(mail_to, user) send_email( From da2dae2ab0e8a751525f919fc0cb9ace648e6baa Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jun 12 2015 16:23:59 +0000 Subject: [PATCH 16/16] Rename the two regex to something a little more self-explanatory --- diff --git a/pagure/forms.py b/pagure/forms.py index 56b530e..9ac55d3 100644 --- a/pagure/forms.py +++ b/pagure/forms.py @@ -14,8 +14,8 @@ import wtforms # pylint: disable=R0903,W0232,E1002 -REGEX = '^[a-zA-Z0-9-_]+$' -REGEX2 = '^[a-zA-Z0-9 #]+$' +STRICT_REGEX = '^[a-zA-Z0-9-_]+$' +RELAXED_REGEX = '^[a-zA-Z0-9 #]+$' class ProjectFormSimplified(wtf.Form): @@ -40,7 +40,7 @@ class ProjectForm(ProjectFormSimplified): 'Project name *', [ wtforms.validators.Required(), - wtforms.validators.Regexp(REGEX, flags=re.IGNORECASE) + wtforms.validators.Regexp(STRICT_REGEX, flags=re.IGNORECASE) ] ) @@ -51,7 +51,7 @@ class IssueFormSimplied(wtf.Form): 'Title*', [ wtforms.validators.Required(), - wtforms.validators.Regexp(REGEX2, flags=re.IGNORECASE) + wtforms.validators.Regexp(RELAXED_REGEX, flags=re.IGNORECASE) ] ) issue_content = wtforms.TextAreaField( @@ -90,7 +90,7 @@ class RequestPullForm(wtf.Form): 'Title*', [ wtforms.validators.Required(), - wtforms.validators.Regexp(REGEX2, flags=re.IGNORECASE) + wtforms.validators.Regexp(RELAXED_REGEX, flags=re.IGNORECASE) ] ) @@ -101,7 +101,7 @@ class AddIssueTagForm(wtf.Form): 'tag', [ wtforms.validators.Optional(), - wtforms.validators.Regexp(REGEX, flags=re.IGNORECASE) + wtforms.validators.Regexp(STRICT_REGEX, flags=re.IGNORECASE) ] ) @@ -152,7 +152,7 @@ class UpdateIssueForm(wtf.Form): 'tag', [ wtforms.validators.Optional(), - wtforms.validators.Regexp(REGEX, flags=re.IGNORECASE) + wtforms.validators.Regexp(STRICT_REGEX, flags=re.IGNORECASE) ] ) depends = wtforms.TextField( @@ -233,7 +233,7 @@ class AddGroupForm(wtf.Form): 'Group *', [ wtforms.validators.Required(), - wtforms.validators.Regexp(REGEX, flags=re.IGNORECASE) + wtforms.validators.Regexp(STRICT_REGEX, flags=re.IGNORECASE) ] ) @@ -283,7 +283,7 @@ class NewGroupForm(wtf.Form): [ wtforms.validators.Required(), wtforms.validators.Length(max=16), - wtforms.validators.Regexp(REGEX, flags=re.IGNORECASE) + wtforms.validators.Regexp(STRICT_REGEX, flags=re.IGNORECASE) ] ) group_type = wtforms.SelectField(