Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #285 #317

Merged
merged 1 commit into from
Jul 6, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions cadasta/accounts/forms.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django import forms
from django.conf import settings
from django.utils.translation import ugettext as _

from .models import User
Expand All @@ -14,19 +15,24 @@ class Meta:
fields = ['username', 'email', 'password1', 'password2',
'full_name']

def clean_username(self):
username = self.data.get('username')
if username.lower() in settings.CADASTA_INVALID_ENTITY_NAMES:
raise forms.ValidationError(
_("Username cannot be “add” or “new”."))
return username

def clean_password1(self):
password = self.data.get('password1')
if password != self.data.get('password2'):
raise forms.ValidationError(_("Passwords do not match"))

return password

def clean_email(self):
email = self.data.get('email')
if User.objects.filter(email=email).exists():
raise forms.ValidationError(
_("Another user with this email already exists"))

return email

def save(self, *args, **kwargs):
Expand All @@ -47,7 +53,9 @@ def clean_username(self):
User.objects.filter(username=username).exists()):
raise forms.ValidationError(
_("Another user with this username already exists"))

if username.lower() in settings.CADASTA_INVALID_ENTITY_NAMES:
raise forms.ValidationError(
_("Username cannot be “add” or “new”."))
return username

def clean_email(self):
Expand All @@ -56,5 +64,4 @@ def clean_email(self):
User.objects.filter(email=email).exists()):
raise forms.ValidationError(
_("Another user with this email already exists"))

return email
11 changes: 10 additions & 1 deletion cadasta/accounts/serializers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.conf import settings
from django.utils import timezone

from django.utils.translation import ugettext as _

from rest_framework.serializers import EmailField, ValidationError
Expand Down Expand Up @@ -33,6 +33,12 @@ class Meta:
'email': {'required': True, 'unique': True}
}

def validate_username(self, username):
if username.lower() in settings.CADASTA_INVALID_ENTITY_NAMES:
raise ValidationError(
_("Username cannot be “add” or “new”."))
return username


class UserSerializer(djoser_serializers.UserSerializer):
email = EmailField(
Expand Down Expand Up @@ -64,6 +70,9 @@ def validate_username(self, username):
username != instance.username and
self.context['request'].user != instance):
raise ValidationError('Cannot update username')
if username.lower() in settings.CADASTA_INVALID_ENTITY_NAMES:
raise ValidationError(
_("Username cannot be “add” or “new”."))
return username

def validate_last_login(self, last_login):
Expand Down
30 changes: 30 additions & 0 deletions cadasta/accounts/tests/test_forms.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import random

from django.utils.translation import gettext as _

from ..models import User
Expand Down Expand Up @@ -55,6 +57,22 @@ def test_signup_with_existing_email(self):
in form.errors.get('email'))
assert User.objects.count() == 1

def test_signup_with_restricted_username(self):
invalid_usernames = ('add', 'ADD', 'Add', 'new', 'NEW', 'New')
data = {
'username': random.choice(invalid_usernames),
'email': '[email protected]',
'password1': 'iloveyoko79',
'password2': 'iloveyoko68',
'full_name': 'John Lennon',
}
form = RegisterForm(data)

assert form.is_valid() is False
assert (_("Username cannot be “add” or “new”.")
in form.errors.get('username'))
assert User.objects.count() == 0


class ProfileFormTest(UserTestCase):
def test_update_user(self):
Expand Down Expand Up @@ -94,3 +112,15 @@ def test_update_user_with_existing_email(self):
}
form = ProfileForm(data, instance=user)
assert form.is_valid() is False

def test_update_user_with_restricted_username(self):
user = UserFactory.create(username='imagine71',
email='[email protected]')
invalid_usernames = ('add', 'ADD', 'Add', 'new', 'NEW', 'New')
data = {
'username': random.choice(invalid_usernames),
'email': '[email protected]',
'full_name': 'John Lennon',
}
form = ProfileForm(data, instance=user)
assert form.is_valid() is False
38 changes: 36 additions & 2 deletions cadasta/accounts/tests/test_serializers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import random
import pytest
from datetime import datetime
from django.utils.translation import gettext as _
Expand Down Expand Up @@ -73,6 +74,21 @@ def test_create_with_existing_email(self):
assert (_("Another user is already registered with this email address")
in serializer._errors['email'])

def test_create_with_restricted_username(self):
invalid_usernames = ('add', 'ADD', 'Add', 'new', 'NEW', 'New')
data = {
'username': random.choice(invalid_usernames),
'email': '[email protected]',
'password': 'iloveyoko79',
'password_repeat': 'iloveyoko79',
'full_name': 'John Lennon',
}

serializer = RegistrationSerializer(data=data)
assert not serializer.is_valid()
assert (_("Username cannot be “add” or “new”.")
in serializer._errors['username'])


class UserSerializerTest(UserTestCase):
def test_field_serialization(self):
Expand Down Expand Up @@ -102,8 +118,7 @@ def test_create_with_valid_data(self):
def test_update_username_fails(self):
serializer = UserSerializer(data=BASIC_TEST_DATA)
assert serializer.is_valid()
serializer.save()
user = User.objects.first()
user = serializer.save()
other_user = UserFactory.create()
update_data = {'username': 'bad-update'}
request = APIRequestFactory().patch('/user/imagine71', update_data)
Expand All @@ -125,6 +140,25 @@ def test_update_last_login_fails(self):
assert not serializer2.is_valid()
assert serializer2.errors['last_login'] == ['Cannot update last_login']

def test_update_with_restricted_username(self):
serializer = UserSerializer(data=BASIC_TEST_DATA)
assert serializer.is_valid()
user = serializer.save()
invalid_usernames = ('add', 'ADD', 'Add', 'new', 'NEW', 'New')
data = {
'username': random.choice(invalid_usernames),
'email': '[email protected]',
'full_name': 'John Lennon',
}
request = APIRequestFactory().patch('/user/imagine71', data)
force_authenticate(request, user=user)
serializer2 = UserSerializer(
user, data=data, context={'request': Request(request)}
)
assert not serializer2.is_valid()
assert serializer2.errors['username'] == [
_("Username cannot be “add” or “new”.")]


class AccountLoginSerializerTest(UserTestCase):
def test_unverified_account(self):
Expand Down
3 changes: 3 additions & 0 deletions cadasta/config/settings/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@
}
}

# Invalid names for Cadasta organizations, projects, and usernames
CADASTA_INVALID_ENTITY_NAMES = ['add', 'new']

# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/

Expand Down
22 changes: 20 additions & 2 deletions cadasta/organization/forms.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from django import forms
from django.conf import settings
from django.contrib.postgres import forms as pg_forms
from django.contrib.gis import forms as gisforms
from django.utils.text import slugify
from django.utils.translation import ugettext as _
from django.db import transaction

Expand Down Expand Up @@ -96,13 +98,22 @@ def to_list(self, value):
def clean_urls(self):
return self.to_list(self.data.get('urls'))

def clean_name(self):
is_create = not self.instance.id
name = self.cleaned_data['name']
invalid_names = settings.CADASTA_INVALID_ENTITY_NAMES
if is_create and slugify(name) in invalid_names:
raise forms.ValidationError(
_("Organization name cannot be “Add” or “New”."))
return name

def save(self, *args, **kwargs):
instance = super(OrganizationForm, self).save(commit=False)
create = not instance.id
is_create = not instance.id

instance.save()

if create:
if is_create:
OrganizationRole.objects.create(
organization=instance,
user=self.user,
Expand Down Expand Up @@ -208,6 +219,13 @@ def __init__(self, *args, **kwargs):
(o.slug, o.name) for o in Organization.objects.order_by('name')
]

def clean_name(self):
name = self.cleaned_data['name']
if slugify(name) in settings.CADASTA_INVALID_ENTITY_NAMES:
raise forms.ValidationError(
_("Project name cannot be “Add” or “New”."))
return name


class ProjectEditDetails(forms.ModelForm):
urls = pg_forms.SimpleArrayField(forms.URLField(), required=False)
Expand Down
17 changes: 17 additions & 0 deletions cadasta/organization/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from django.db.models import Q
from django.core.mail import send_mail
from django.core.urlresolvers import reverse
from django.utils.text import slugify
from django.utils.translation import ugettext as _
from django.template.loader import get_template
from django.template import Context
Expand All @@ -26,6 +27,14 @@ class Meta:
read_only_fields = ('id', 'slug',)
detail_only_fields = ('users',)

def validate_name(self, value):
is_create = not self.instance
invalid_names = settings.CADASTA_INVALID_ENTITY_NAMES
if is_create and slugify(value) in invalid_names:
raise serializers.ValidationError(
_("Organization name cannot be “Add” or “New”."))
return value

def create(self, *args, **kwargs):
org = super(OrganizationSerializer, self).create(*args, **kwargs)

Expand All @@ -43,6 +52,14 @@ class ProjectSerializer(DetailSerializer, serializers.ModelSerializer):
organization = OrganizationSerializer(read_only=True)
country = CountryField(required=False)

def validate_name(self, value):
is_create = not self.instance
invalid_names = settings.CADASTA_INVALID_ENTITY_NAMES
if is_create and slugify(value) in invalid_names:
raise serializers.ValidationError(
_("Project name cannot be “Add” or “New”."))
return value

class Meta:
model = Project
fields = ('id', 'organization', 'country', 'name', 'description',
Expand Down
40 changes: 39 additions & 1 deletion cadasta/organization/tests/test_forms.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import random
from pytest import raises

from django.conf import settings
Expand All @@ -18,7 +19,7 @@
from tutelary.models import Policy


class OrganzationTest(UserTestCase):
class OrganizationTest(UserTestCase):
def setUp(self):
super().setUp()
self.data = {
Expand Down Expand Up @@ -77,6 +78,23 @@ def test_add_organization_with_contact(self):
'email': '[email protected]'
}]

def test_add_organization_with_restricted_name(self):
invalid_names = ('add', 'ADD', 'Add', 'new', 'NEW', 'New')
data = {
'name': random.choice(invalid_names),
'contacts-TOTAL_FORMS': 1,
'contacts-INITIAL_FORMS': 0,
'contacts-0-name': '',
'contacts-0-email': '',
'contacts-0-tel': ''
}
form = forms.OrganizationForm(data, user=UserFactory.create())
assert not form.is_valid()
assert form.errors == {
'name': ["Organization name cannot be “Add” or “New”."]
}
assert not Organization.objects.exists()

def test_update_organization(self):
org = OrganizationFactory.create(slug='some-org')
self.data['description'] = 'Org description'
Expand Down Expand Up @@ -216,6 +234,26 @@ def test_edit_project_roles(self):
is False)


class ProjectAddDetailsTest(UserTestCase):
def test_add_new_project_with_restricted_name(self):
org = OrganizationFactory.create()
invalid_names = ('add', 'ADD', 'Add', 'new', 'NEW', 'New')
data = {
'organization': org.slug,
'name': random.choice(invalid_names),
'contacts-TOTAL_FORMS': 1,
'contacts-INITIAL_FORMS': 0,
'contacts-0-name': '',
'contacts-0-email': '',
'contacts-0-tel': ''
}
form = forms.ProjectAddDetails(data=data)
assert not form.is_valid()
assert form.errors == {
'name': ["Project name cannot be “Add” or “New”."]
}


class ProjectEditDetailsTest(UserTestCase):
def _get_form(self, form_name):
path = os.path.dirname(settings.BASE_DIR)
Expand Down
Loading