From 7ac41be37b4f006a0e2524ebcec92e8af011e712 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 10 Sep 2017 12:16:24 +0200 Subject: [PATCH 01/76] Use new FlaskForm API --- debianmemberportfolio/forms.py | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/debianmemberportfolio/forms.py b/debianmemberportfolio/forms.py index 4c9612e..85ccadf 100644 --- a/debianmemberportfolio/forms.py +++ b/debianmemberportfolio/forms.py @@ -1,7 +1,29 @@ +# -*- python -*- +# -*- coding: utf-8 -*- +# +# Debian Member Portfolio Service views +# +# Copyright © 2015-2017 Jan Dittberner +# +# This file is part of the Debian Member Portfolio Service. +# +# Debian Member Portfolio Service is free software: you can redistribute it +# and/or modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the License, +# or (at your option) any later version. +# +# Debian Member Portfolio Service is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# from __future__ import unicode_literals from flask_babel import gettext as _ -from flask_wtf import Form +from flask_wtf import FlaskForm from wtforms import IntegerField, StringField, RadioField from wtforms.validators import ( AnyOf, DataRequired, Email, Length, Optional, Regexp @@ -18,7 +40,7 @@ class PlainText(Regexp): super(PlainText, self).__init__(r'^[a-zA-Z\-0-9]*$') -class DeveloperData(Form): +class DeveloperData(FlaskForm): email = StringField('email', validators=[DataRequired(), Email()]) name = StringField('name', validators=[DataRequired()]) gpgfp = StringField('gpgfp', validators=[ @@ -38,5 +60,5 @@ class DeveloperData(Form): Optional()]) -class DeveloperDataRequest(Form): +class DeveloperDataRequest(FlaskForm): email = StringField('email', validators=[DataRequired(), Email()]) From 178767102cb4ff2ea971d1c2fd6ab3ede0654ed2 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 10 Sep 2017 12:17:05 +0200 Subject: [PATCH 02/76] Bump version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 0a8c9f9..d540125 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ except ImportError: setup( name='debianmemberportfolio', - version='0.5.0', + version='0.5.1', description='service to create Debian Member Portfolio URLs', long_description="""This is a service implementation that returns a set of personalized URLs as outlined in https://wiki.debian.org/DDPortfolio. It From ff3cc9d940d400eeb7669ca01f5bc1ffc2bb4b3f Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Tue, 12 Sep 2017 21:58:46 +0200 Subject: [PATCH 03/76] Fix issues with incompletely filled forms This commit reintroduces support for forms with email address as the only mandatory parameter. --- debianmemberportfolio/forms.py | 13 +++++++------ debianmemberportfolio/model/urlbuilder.py | 4 ++-- debianmemberportfolio/views.py | 23 ++++++++++++----------- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/debianmemberportfolio/forms.py b/debianmemberportfolio/forms.py index 85ccadf..11f6b14 100644 --- a/debianmemberportfolio/forms.py +++ b/debianmemberportfolio/forms.py @@ -42,14 +42,15 @@ class PlainText(Regexp): class DeveloperData(FlaskForm): email = StringField('email', validators=[DataRequired(), Email()]) - name = StringField('name', validators=[DataRequired()]) + name = StringField('name', validators=[Optional(), DataRequired()]) gpgfp = StringField('gpgfp', validators=[ - FingerPrint(), - Length(min=32, max=40) + Optional(), FingerPrint(), Length(min=32, max=40) + ]) + username = StringField('username', validators=[Optional(), PlainText()]) + nonddemail = StringField('nonddemail', validators=[Optional(), Email()]) + aliothusername = StringField('aliothusername', validators=[ + Optional(), PlainText() ]) - username = StringField('username', validators=[PlainText()]) - nonddemail = StringField('nonddemail', validators=[Email()]) - aliothusername = StringField('aliothusername', validators=[PlainText()]) mode = RadioField( 'mode', default='html', choices=[ ('json', _('JSON')), ('html', _('HTML')) diff --git a/debianmemberportfolio/model/urlbuilder.py b/debianmemberportfolio/model/urlbuilder.py index f948ddc..d84e302 100644 --- a/debianmemberportfolio/model/urlbuilder.py +++ b/debianmemberportfolio/model/urlbuilder.py @@ -3,7 +3,7 @@ # # Debian Member Portfolio Service url builder # -# Copyright © 2009-2015 Jan Dittberner +# Copyright © 2009-2017 Jan Dittberner # # This file is part of the Debian Member Portfolio Service. # @@ -73,7 +73,7 @@ def _build_quoted_fields(fields): qfields[key] = quote_plus(value) else: qfields[key] = value - qfields[key] = qfields[key].replace('%', '%%') + qfields[key] = str(qfields[key]).replace('%', '%%') if 'gpgfp' not in qfields: fpr = keyfinder.getFingerprintByEmail(fields['email'].encode('utf8')) diff --git a/debianmemberportfolio/views.py b/debianmemberportfolio/views.py index 467ad2f..dd88aa3 100644 --- a/debianmemberportfolio/views.py +++ b/debianmemberportfolio/views.py @@ -3,7 +3,7 @@ # # Debian Member Portfolio Service views # -# Copyright © 2015 Jan Dittberner +# Copyright © 2015-2017 Jan Dittberner # # This file is part of the Debian Member Portfolio Service. # @@ -162,25 +162,26 @@ def urllist(): form = DeveloperData(request.values) if form.validate(): fields = dddatabuilder.build_data(form.data['email']) - rp = request.values + + form_data = form.data.copy() if fields['type'] in (dddatabuilder.TYPE_DD, dddatabuilder.TYPE_DM): for dmtuple in DM_TUPLES: - if not dmtuple[0] in rp or not rp[dmtuple[0]]: - rp[dmtuple[0]] = fields[dmtuple[1]] + if not form_data[dmtuple[0]]: + form_data[dmtuple[0]] = fields[dmtuple[1]] if fields['type'] == dddatabuilder.TYPE_DD: for ddtuple in DD_TUPLES: - if not ddtuple[0] in rp or not rp[ddtuple[0]]: - rp[ddtuple[0]] = fields[ddtuple[1]] - if form.data['wikihomepage'] is None: + if not form_data[ddtuple[0]]: + form_data[ddtuple[0]] = fields[ddtuple[1]] + if not form_data['wikihomepage']: log.debug('generate wikihomepage from name') - form.data['wikihomepage'] = "".join([ - part.capitalize() for part in form.data['name'].split() + form_data['wikihomepage'] = "".join([ + part.capitalize() for part in form_data['name'].split() ]) - data = build_urls(form.data) + data = build_urls(form_data) - if form.data['mode'] == 'json': + if form_data['mode'] == 'json': response = make_response(json.dumps(dict( [("{}.{}".format(entry[1], entry[2].name), entry[3]) for entry in data if entry[0] == 'url']))) From f11114f58047f50d0a71f42e4e24e4bbb1e04b64 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Tue, 12 Sep 2017 22:13:02 +0200 Subject: [PATCH 04/76] Strip non hexadecimal characters from GPG fingerprint input This commit removes non hexadecimal characters from entered GPG fingerprint values to allow copy and paste from gpg output. --- debianmemberportfolio/forms.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/debianmemberportfolio/forms.py b/debianmemberportfolio/forms.py index 11f6b14..d4c87fc 100644 --- a/debianmemberportfolio/forms.py +++ b/debianmemberportfolio/forms.py @@ -28,6 +28,7 @@ from wtforms import IntegerField, StringField, RadioField from wtforms.validators import ( AnyOf, DataRequired, Email, Length, Optional, Regexp ) +from string import hexdigits class FingerPrint(Regexp): @@ -40,10 +41,17 @@ class PlainText(Regexp): super(PlainText, self).__init__(r'^[a-zA-Z\-0-9]*$') +def gpg_fingerprint(data): + if data is not None: + return "".join([ + char for char in str(data) if char.lower() in hexdigits]) + return data + + class DeveloperData(FlaskForm): email = StringField('email', validators=[DataRequired(), Email()]) name = StringField('name', validators=[Optional(), DataRequired()]) - gpgfp = StringField('gpgfp', validators=[ + gpgfp = StringField('gpgfp', filters=[gpg_fingerprint], validators=[ Optional(), FingerPrint(), Length(min=32, max=40) ]) username = StringField('username', validators=[Optional(), PlainText()]) From 0247ac612b3ad3275b7ee1b7387144e4f1192359 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Tue, 12 Sep 2017 22:14:47 +0200 Subject: [PATCH 05/76] Bump version to 0.5.2 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index d540125..052ce33 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ except ImportError: setup( name='debianmemberportfolio', - version='0.5.1', + version='0.5.2', description='service to create Debian Member Portfolio URLs', long_description="""This is a service implementation that returns a set of personalized URLs as outlined in https://wiki.debian.org/DDPortfolio. It From a627c20031e53c0fe0c71d32609db7a4bf6811fd Mon Sep 17 00:00:00 2001 From: Paul Wise Date: Wed, 10 Jan 2018 12:13:27 +0800 Subject: [PATCH 06/76] Add username for and link to the Salsa service Salsa will be gradually replacing the Alioth service. --- debianmemberportfolio/forms.py | 3 +++ debianmemberportfolio/model/portfolio.ini | 2 ++ debianmemberportfolio/model/urlbuilder.py | 1 + debianmemberportfolio/templates/showform.html | 7 +++++++ debianmemberportfolio/templates/showformscript.js | 12 ++++++++---- debianmemberportfolio/views.py | 2 ++ docs/source/devdocs.rst | 2 ++ 7 files changed, 25 insertions(+), 4 deletions(-) diff --git a/debianmemberportfolio/forms.py b/debianmemberportfolio/forms.py index d4c87fc..a309dcd 100644 --- a/debianmemberportfolio/forms.py +++ b/debianmemberportfolio/forms.py @@ -56,6 +56,9 @@ class DeveloperData(FlaskForm): ]) username = StringField('username', validators=[Optional(), PlainText()]) nonddemail = StringField('nonddemail', validators=[Optional(), Email()]) + salsausername = StringField('salsausername', validators=[ + Optional(), PlainText() + ]) aliothusername = StringField('aliothusername', validators=[ Optional(), PlainText() ]) diff --git a/debianmemberportfolio/model/portfolio.ini b/debianmemberportfolio/model/portfolio.ini index 3a45504..921d5ba 100644 --- a/debianmemberportfolio/model/portfolio.ini +++ b/debianmemberportfolio/model/portfolio.ini @@ -78,6 +78,8 @@ db.pattern=https://db.debian.org/search.cgi?uid=%(username)s&dosearch=Search db.optional=true webid.pattern=http://webid.debian.net/maintainers/%(username)s webid.optional=true +salsa.pattern=https://salsa.debian.org/%(salsausername)s +salsa.optional=true alioth.pattern=https://alioth.debian.org/users/%(aliothusername)s/ alioth.optional=true wiki.pattern=https://wiki.debian.org/%(wikihomepage)s diff --git a/debianmemberportfolio/model/urlbuilder.py b/debianmemberportfolio/model/urlbuilder.py index d84e302..d107fc8 100644 --- a/debianmemberportfolio/model/urlbuilder.py +++ b/debianmemberportfolio/model/urlbuilder.py @@ -45,6 +45,7 @@ _FIELDNAMES_MAP = { 'gpgfp': N_('GPG fingerprint'), 'username': N_('Debian user name'), 'nonddemail': N_('Non Debian email address'), + 'salsausername': N_('Salsa user name'), 'aliothusername': N_('Alioth user name'), } diff --git a/debianmemberportfolio/templates/showform.html b/debianmemberportfolio/templates/showform.html index e0b40c0..ccef9f2 100644 --- a/debianmemberportfolio/templates/showform.html +++ b/debianmemberportfolio/templates/showform.html @@ -67,6 +67,13 @@ with this program. If not, see .
{{ form.nonddemail }} +
+
+ {{ form.salsausername }} +