Jan Dittberner
29b05952d7
- fix internal server error when name is missing for non Debian member - fix unicode handling in urlbuilder
142 lines
5 KiB
Python
142 lines
5 KiB
Python
# -*- python -*-
|
|
# -*- coding: utf8 -*-
|
|
#
|
|
# Debian Member Portfolio Service url builder
|
|
#
|
|
# Copyright © 2009-2023 Jan Dittberner <jan@dittberner.info>
|
|
#
|
|
# 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 <https://www.gnu.org/licenses/>.
|
|
#
|
|
"""
|
|
This module provides the function build_urls to build personalized
|
|
URLs using the given information and the URL patterns defined in
|
|
portfolio.ini.
|
|
"""
|
|
|
|
from configparser import ConfigParser, InterpolationMissingOptionError
|
|
from encodings.utf_8 import StreamReader as UTF8StreamReader
|
|
from importlib import resources
|
|
from urllib.parse import quote_plus
|
|
|
|
from debianmemberportfolio.model import keyfinder
|
|
from flask_babel import gettext as _
|
|
from flask_babel import lazy_gettext as N_
|
|
|
|
my_config = ConfigParser()
|
|
ref = resources.files("debianmemberportfolio.model").joinpath("portfolio.ini")
|
|
with ref.open("rb") as fp:
|
|
my_config.read_file(UTF8StreamReader(fp))
|
|
|
|
_FIELDNAMES_MAP = {
|
|
"email": N_("Email address"),
|
|
"name": N_("Name"),
|
|
"openpgpfp": N_("OpenPGP fingerprint"),
|
|
"username": N_("Debian user name"),
|
|
"nonddemail": N_("Non Debian email address"),
|
|
"salsausername": N_("Salsa user name"),
|
|
}
|
|
|
|
|
|
class DDPortfolioEntry(object):
|
|
def __init__(self, config, section, key):
|
|
self.name = key
|
|
self.optional = (
|
|
config.has_option(section, key + ".optional")
|
|
and config.getboolean(section, key + ".optional")
|
|
or False
|
|
)
|
|
if config.has_option(section, key + ".type"):
|
|
self.type = config.get(section, key + ".type")
|
|
else:
|
|
self.type = "url"
|
|
|
|
|
|
def _build_quoted_fields(fields):
|
|
"""
|
|
Take a dictionary of raw field values and quote the values if required.
|
|
"""
|
|
qfields = {}
|
|
for key, value in fields.items():
|
|
if value is not None:
|
|
if isinstance(value, str):
|
|
qfields[key] = quote_plus(value.encode("utf8"))
|
|
elif isinstance(value, str):
|
|
qfields[key] = quote_plus(value)
|
|
else:
|
|
qfields[key] = value
|
|
qfields[key] = str(qfields[key]).replace("%", "%%")
|
|
|
|
if "openpgpfp" not in qfields:
|
|
fpr = keyfinder.getFingerprintByEmail(fields["email"])
|
|
if fpr:
|
|
qfields["openpgpfp"] = fpr[0]
|
|
qfields["firstchar"] = fields["email"][0]
|
|
qfields["emailnoq"] = fields["email"]
|
|
return qfields
|
|
|
|
|
|
def build_urls(fields):
|
|
"""Build personalized URLs using the developer information in
|
|
fields."""
|
|
data = []
|
|
quoted_fields = _build_quoted_fields(fields)
|
|
for section in [
|
|
section.strip()
|
|
for section in my_config.get("DEFAULT", "urlbuilder.sections").split(",")
|
|
]:
|
|
data.append(["section", section])
|
|
if my_config.has_option(section, "urls"):
|
|
for entry in [
|
|
DDPortfolioEntry(my_config, section, url)
|
|
for url in my_config.get(section, "urls").split(",")
|
|
]:
|
|
try:
|
|
data.append(
|
|
[
|
|
"url",
|
|
section,
|
|
entry,
|
|
my_config.get(
|
|
section,
|
|
entry.name + ".pattern",
|
|
raw=False,
|
|
vars=quoted_fields,
|
|
),
|
|
]
|
|
)
|
|
except InterpolationMissingOptionError as e:
|
|
if not entry.optional:
|
|
if e.reference in _FIELDNAMES_MAP:
|
|
data.append(
|
|
[
|
|
"error",
|
|
section,
|
|
entry,
|
|
_("Missing input: %s")
|
|
% _(_FIELDNAMES_MAP[e.reference]),
|
|
]
|
|
)
|
|
else:
|
|
data.append(
|
|
[
|
|
"error",
|
|
section,
|
|
entry,
|
|
_("Missing input: %s") % e.reference,
|
|
]
|
|
)
|
|
return data
|