diff --git a/gratipay/exceptions.py b/gratipay/exceptions.py index ac33104056..87494773f0 100644 --- a/gratipay/exceptions.py +++ b/gratipay/exceptions.py @@ -57,6 +57,7 @@ class NoSelfTipping(Exception): pass class NoTippee(Exception): pass class NoTeam(Exception): pass class BadAmount(Exception): pass +class InvalidTeamName(Exception): pass class FailedToReserveUsername(Exception): pass diff --git a/gratipay/models/team.py b/gratipay/models/team.py index adac4208e8..d149ac6985 100644 --- a/gratipay/models/team.py +++ b/gratipay/models/team.py @@ -1,10 +1,28 @@ """Teams on Gratipay receive payments and distribute payroll. """ +import re import requests from aspen import json, log +from gratipay.exceptions import InvalidTeamName from gratipay.models import add_event from postgres.orm import Model +# Should have at least one alphabet. +TEAM_NAME_PATTERN = re.compile(r'^(?=.*[A-Za-z])([A-Za-z0-9.,-_ ]+)$') + +def slugize(name): + """ Create a slug from a team name. + """ + if TEAM_NAME_PATTERN.match(name) is None: + raise InvalidTeamName + + slug = name.strip() + for c in (',', ' '): + slug = slug.replace(c, '-') # Avoid % encoded characters in slug url. + while '--' in slug: + slug = slug.replace('--', '-') + slug = slug.strip('-') + return slug class Team(Model): """Represent a Gratipay team. diff --git a/www/teams/create.json.spt b/www/teams/create.json.spt index 5a6a510c93..a294633e3b 100644 --- a/www/teams/create.json.spt +++ b/www/teams/create.json.spt @@ -72,7 +72,7 @@ if request.method == 'POST': try: fields['slug'] = slugize(fields['name']) - except AssertionError: + except InvalidTeamName: raise Response(400, _("Sorry, team name contains invalid characters.")) try: