Skip to content

Commit 7074d5d

Browse files
renzonrenzon
authored andcommitted
Migrate emails to lower case
Conflicting emails are been logged to manual handling close #1694
1 parent 04ff902 commit 7074d5d

File tree

5 files changed

+114
-33
lines changed

5 files changed

+114
-33
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ wheels/
2424
*.egg-info/
2525
.installed.cfg
2626
*.egg
27+
dumps/
2728

2829
# PyInstaller
2930
# Usually these files are written by a python script from a template

Pipfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ pytest-django = "*"
3939
pytest-freezegun = "*"
4040
pytest-mock = "*"
4141
pytest = "*"
42+
django-test-migrations = "*"
4243

4344
[requires]
4445
python_version = "3.8"

Pipfile.lock

Lines changed: 41 additions & 33 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Generated by Django 3.0.3 on 2020-02-28 11:30
2+
3+
from django.db import IntegrityError, migrations
4+
5+
from django.db.transaction import atomic
6+
7+
8+
def normalize_email(apps, schema_editor):
9+
'''
10+
We can't import the Post model directly as it may be a newer
11+
version than this migration expects. We use the historical version.
12+
'''
13+
User = apps.get_model('core', 'User')
14+
print()
15+
for msg in normalize_all_users_email(User):
16+
print(msg)
17+
18+
19+
def normalize_all_users_email(User):
20+
for user in User.objects.order_by('id').all():
21+
original_email = user.email
22+
normalized_email = user.email.lower()
23+
if normalized_email != original_email:
24+
user.email = normalized_email
25+
try:
26+
with atomic():
27+
user.save()
28+
except IntegrityError:
29+
yield f'Normalization error user {user.id}, {original_email}'
30+
31+
32+
class Migration(migrations.Migration):
33+
dependencies = [
34+
('core', '0009_auto_20191031_1324'),
35+
]
36+
37+
operations = [
38+
migrations.RunPython(normalize_email, migrations.RunPython.noop)
39+
]
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from importlib import import_module
2+
3+
from model_mommy import mommy
4+
5+
# Workaround since module beginning with number can't be imported in regular way
6+
migration_module = import_module('pythonpro.core.migrations.0010_normalizing_email')
7+
8+
9+
def test_user_email_normalization_success(django_user_model):
10+
"""Ensures email can be normalized"""
11+
12+
upper_email = 'UPPER@python.pro.br'
13+
mommy.make(django_user_model, email=upper_email)
14+
msg = next(migration_module.normalize_all_users_email(django_user_model), None)
15+
assert msg is None
16+
assert django_user_model.objects.first().email == upper_email.lower()
17+
18+
19+
def test_no_msg_for_already_normalized_emails(django_user_model):
20+
mommy.make(django_user_model, email='lower@python.pro.br')
21+
msg = next(migration_module.normalize_all_users_email(django_user_model), None)
22+
assert msg is None
23+
24+
25+
def test_conflictiong_email_msg(django_user_model):
26+
lower_email = 'normalized@python.pro.br'
27+
upper_email = 'NORMALIZED@python.pro.br'
28+
upper_email_user = mommy.make(django_user_model, email=upper_email)
29+
mommy.make(django_user_model, email=lower_email)
30+
msg = next(migration_module.normalize_all_users_email(django_user_model))
31+
upper_email_user = django_user_model.objects.get(id=upper_email_user.id)
32+
assert msg == f'Normalization error user {upper_email_user.id}, {upper_email_user.email}'

0 commit comments

Comments
 (0)