Merge pull request #453 from taigaio/filter-by-email-domain-on-register

Add filter by email domain on register
remotes/origin/issue/4795/notification_even_they_are_disabled
David Barragán Merino 2016-07-08 13:04:04 +02:00 committed by GitHub
commit bc3025f065
8 changed files with 164 additions and 1 deletions

View File

@ -22,6 +22,7 @@
- Import/Export:
- Gzip export/import support.
- Export performance improvements.
- Add filter by email domain registration and invitation by setting.
### Misc
- [API] Improve performance of some calls over list.

View File

@ -441,6 +441,8 @@ APP_EXTRA_EXPOSE_HEADERS = [
DEFAULT_PROJECT_TEMPLATE = "scrum"
PUBLIC_REGISTER_ENABLED = False
# None or [] values in USER_EMAIL_ALLOWED_DOMAINS means allow any domain
USER_EMAIL_ALLOWED_DOMAINS = None
SEARCHES_MAX_RESULTS = 150

View File

@ -105,3 +105,7 @@ DATABASES = {
# To use celery in memory
#CELERY_ENABLED = True
#CELERY_ALWAYS_EAGER = True
# LIMIT ALLOWED DOMAINS FOR REGISTER AND INVITE
# None or [] values in USER_EMAIL_ALLOWED_DOMAINS means allow any domain
# USER_EMAIL_ALLOWED_DOMAINS = None

View File

@ -612,6 +612,14 @@ class ChoiceField(WritableField):
return value
def validate_user_email_allowed_domains(value):
domain_name = value.split("@")[1]
print("EMAIL VALIDATE DOMAIN")
if settings.USER_EMAIL_ALLOWED_DOMAINS and domain_name not in settings.USER_EMAIL_ALLOWED_DOMAINS:
raise ValidationError(_("You email domain is not allowed"))
class EmailField(CharField):
type_name = "EmailField"
type_label = "email"
@ -620,7 +628,7 @@ class EmailField(CharField):
default_error_messages = {
"invalid": _("Enter a valid email address."),
}
default_validators = [validators.validate_email]
default_validators = [validators.validate_email, validate_user_email_allowed_domains]
def from_native(self, value):
ret = super(EmailField, self).from_native(value)

View File

@ -33,6 +33,7 @@ from taiga.base.decorators import list_route
from taiga.base.decorators import detail_route
from taiga.base.api import ModelCrudViewSet
from taiga.base.api.mixins import BlockedByProjectMixin
from taiga.base.api.fields import validate_user_email_allowed_domains
from taiga.base.api.utils import get_object_or_404
from taiga.base.filters import MembersFilterBackend
from taiga.base.mails import mail_builder
@ -112,6 +113,7 @@ class UsersViewSet(ModelCrudViewSet):
try:
validate_email(new_email)
validate_user_email_allowed_domains(new_email)
except ValidationError:
valid_new_email = False

View File

@ -48,6 +48,20 @@ def test_respond_400_when_public_registration_is_disabled(client, register_form,
assert response.status_code == 400
def test_respond_400_when_the_email_domain_isnt_in_allowed_domains(client, register_form, settings):
settings.PUBLIC_REGISTER_ENABLED = True
settings.USER_EMAIL_ALLOWED_DOMAINS = ['other-domain.com']
response = client.post(reverse("auth-register"), register_form)
assert response.status_code == 400
def test_respond_201_when_the_email_domain_is_in_allowed_domains(client, settings, register_form):
settings.PUBLIC_REGISTER_ENABLED = True
settings.USER_EMAIL_ALLOWED_DOMAINS = ['email.com']
response = client.post(reverse("auth-register"), register_form)
assert response.status_code == 201
def test_respond_201_with_invitation_without_public_registration(client, register_form, settings):
settings.PUBLIC_REGISTER_ENABLED = False
user = factories.UserFactory()

View File

@ -72,6 +72,79 @@ def test_api_create_bulk_members(client):
assert response.data[1]["email"] == joseph.email
def test_api_create_bulk_members_with_allowed_domain(client):
project = f.ProjectFactory()
john = f.UserFactory.create()
joseph = f.UserFactory.create()
tester = f.RoleFactory(project=project, name="Tester")
gamer = f.RoleFactory(project=project, name="Gamer")
f.MembershipFactory(project=project, user=project.owner, is_admin=True)
url = reverse("memberships-bulk-create")
data = {
"project_id": project.id,
"bulk_memberships": [
{"role_id": tester.pk, "email": "test1@email.com"},
{"role_id": gamer.pk, "email": "test2@email.com"},
]
}
client.login(project.owner)
response = client.json.post(url, json.dumps(data))
assert response.status_code == 200
assert response.data[0]["email"] == "test1@email.com"
assert response.data[1]["email"] == "test2@email.com"
def test_api_create_bulk_members_with_allowed_and_unallowed_domain(client, settings):
project = f.ProjectFactory()
settings.USER_EMAIL_ALLOWED_DOMAINS = ['email.com']
tester = f.RoleFactory(project=project, name="Tester")
gamer = f.RoleFactory(project=project, name="Gamer")
f.MembershipFactory(project=project, user=project.owner, is_admin=True)
url = reverse("memberships-bulk-create")
data = {
"project_id": project.id,
"bulk_memberships": [
{"role_id": tester.pk, "email": "test@invalid-domain.com"},
{"role_id": gamer.pk, "email": "test@email.com"},
]
}
client.login(project.owner)
response = client.json.post(url, json.dumps(data))
assert response.status_code == 400
assert "email" in response.data["bulk_memberships"][0]
assert "email" not in response.data["bulk_memberships"][1]
def test_api_create_bulk_members_with_unallowed_domains(client, settings):
project = f.ProjectFactory()
settings.USER_EMAIL_ALLOWED_DOMAINS = ['email.com']
tester = f.RoleFactory(project=project, name="Tester")
gamer = f.RoleFactory(project=project, name="Gamer")
f.MembershipFactory(project=project, user=project.owner, is_admin=True)
url = reverse("memberships-bulk-create")
data = {
"project_id": project.id,
"bulk_memberships": [
{"role_id": tester.pk, "email": "test1@invalid-domain.com"},
{"role_id": gamer.pk, "email": "test2@invalid-domain.com"},
]
}
client.login(project.owner)
response = client.json.post(url, json.dumps(data))
assert response.status_code == 400
assert "email" in response.data["bulk_memberships"][0]
assert "email" in response.data["bulk_memberships"][1]
def test_api_create_bulk_members_without_enough_memberships_private_project_slots_one_project(client):
user = f.UserFactory.create(max_memberships_private_projects=3)
project = f.ProjectFactory(owner=user, is_private=True)
@ -314,6 +387,36 @@ def test_api_create_membership(client):
assert response.data["user_email"] == user.email
def test_api_create_membership_with_unallowed_domain(client, settings):
settings.USER_EMAIL_ALLOWED_DOMAINS = ['email.com']
membership = f.MembershipFactory(is_admin=True)
role = f.RoleFactory.create(project=membership.project)
client.login(membership.user)
url = reverse("memberships-list")
data = {"role": role.pk, "project": role.project.pk, "email": "test@invalid-email.com"}
response = client.json.post(url, json.dumps(data))
assert response.status_code == 400
assert "email" in response.data
def test_api_create_membership_with_allowed_domain(client, settings):
settings.USER_EMAIL_ALLOWED_DOMAINS = ['email.com']
membership = f.MembershipFactory(is_admin=True)
role = f.RoleFactory.create(project=membership.project)
client.login(membership.user)
url = reverse("memberships-list")
data = {"role": role.pk, "project": role.project.pk, "email": "test@email.com"}
response = client.json.post(url, json.dumps(data))
assert response.status_code == 201
assert response.data["email"] == "test@email.com"
def test_api_create_membership_without_enough_memberships_private_project_slots_one_projects(client):
user = f.UserFactory.create(max_memberships_private_projects=1)
project = f.ProjectFactory(owner=user, is_private=True)

View File

@ -99,6 +99,35 @@ def test_update_user_with_invalid_email(client):
assert response.data['_error_message'] == 'Not valid email'
def test_update_user_with_unallowed_domain_email(client, settings):
settings.USER_EMAIL_ALLOWED_DOMAINS = ['email.com']
user = f.UserFactory.create(email="my@email.com")
url = reverse('users-detail', kwargs={"pk": user.pk})
data = {"email": "my@invalid-email.com"}
client.login(user)
response = client.patch(url, json.dumps(data), content_type="application/json")
assert response.status_code == 400
assert response.data['_error_message'] == 'Not valid email'
def test_update_user_with_allowed_domain_email(client, settings):
settings.USER_EMAIL_ALLOWED_DOMAINS = ['email.com']
user = f.UserFactory.create(email="old@email.com")
url = reverse('users-detail', kwargs={"pk": user.pk})
data = {"email": "new@email.com"}
client.login(user)
response = client.patch(url, json.dumps(data), content_type="application/json")
assert response.status_code == 200
user = models.User.objects.get(pk=user.id)
assert user.email_token is not None
assert user.new_email == "new@email.com"
def test_update_user_with_valid_email(client):
user = f.UserFactory.create(email="old@email.com")
url = reverse('users-detail', kwargs={"pk": user.pk})