Skip to content

Commit

Permalink
Make static migration
Browse files Browse the repository at this point in the history
Use integer to describe relay.firefox.com or mozmail.com addresses so we can change the values of these based on different environment. Updated tests accordingly.
  • Loading branch information
say-yawn committed Aug 18, 2021
1 parent 9aa604f commit 92dce9c
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 18 deletions.
18 changes: 18 additions & 0 deletions emails/migrations/0018_relayaddress_domain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 2.2.24 on 2021-08-18 15:08

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('emails', '0017_remove_unique_from_address'),
]

operations = [
migrations.AddField(
model_name='relayaddress',
name='domain',
field=models.PositiveSmallIntegerField(choices=[(1, 'RELAY_FIREFOX_DOMAIN'), (2, 'MOZMAIL_DOMAIN')], default=1),
),
]
44 changes: 30 additions & 14 deletions emails/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
from django.contrib.auth.models import User
from django.db import models

from emails.utils import get_email_domain_from_settings

emails_config = apps.get_app_config('emails')


Expand All @@ -20,8 +18,12 @@
NOT_PREMIUM_USER_ERR_MSG = 'You must be a premium subscriber to {}.'
TRY_DIFFERENT_VALUE_ERR_MSG = '{} could not be created, try using a different value.'

DOMAIN_DEFAULT = get_email_domain_from_settings()
DOMAIN_CHOICES = [(item, item) for item in settings.ADDITIONAL_DOMAINS]
DOMAINS = {
'RELAY_FIREFOX_DOMAIN': settings.RELAY_FIREFOX_DOMAIN,
'MOZMAIL_DOMAIN': settings.MOZMAIL_DOMAIN
}
DOMAIN_CHOICES = [(1, 'RELAY_FIREFOX_DOMAIN'), (2, 'MOZMAIL_DOMAIN')]
DEFAULT_DOMAIN = settings.RELAY_FIREFOX_DOMAIN


class Profile(models.Model):
Expand Down Expand Up @@ -149,12 +151,12 @@ def add_subdomain(self, subdomain):
return subdomain


def address_hash(address, subdomain=None, domain=DOMAIN_DEFAULT):
def address_hash(address, subdomain=None, domain=DEFAULT_DOMAIN):
if subdomain:
return sha256(
f'{address}@{subdomain}'.encode('utf-8')
).hexdigest()
if domain == DOMAIN_DEFAULT:
if domain == DEFAULT_DOMAIN:
return sha256(
f'{address}'.encode('utf-8')
).hexdigest()
Expand All @@ -174,6 +176,18 @@ def has_bad_words(value):
)


def get_domain_numerical(domain_address):
# get domain name from the address
domains_keys = list(DOMAINS.keys())
domains_values = list(DOMAINS.values())
domain_name = domains_keys[domains_values.index(domain_address)]
# get domain numerical value from domain name
choices = dict(DOMAIN_CHOICES)
choices_keys = list(choices.keys())
choices_values = list(choices.values())
return choices_keys[choices_values.index(domain_name)]


class CannotMakeSubdomainException(Exception):
"""Exception raised by Profile due to error on subdomain creation.
Expand Down Expand Up @@ -201,11 +215,7 @@ class RelayAddress(models.Model):
address = models.CharField(
max_length=64, default=address_default, unique=True
)
domain = models.CharField(
choices=DOMAIN_CHOICES,
default=DOMAIN_DEFAULT,
max_length=64
)
domain = models.PositiveSmallIntegerField(choices=DOMAIN_CHOICES, default=1)
enabled = models.BooleanField(default=True)
description = models.CharField(max_length=64, blank=True)
created_at = models.DateTimeField(auto_now_add=True, db_index=True)
Expand All @@ -221,7 +231,7 @@ def __str__(self):
def delete(self, *args, **kwargs):
# TODO: create hard bounce receipt rule in AWS for the address
deleted_address = DeletedAddress.objects.create(
address_hash=address_hash(self.address, domain=self.domain),
address_hash=address_hash(self.address, domain=self.domain_value),
num_forwarded=self.num_forwarded,
num_blocked=self.num_blocked,
num_spam=self.num_spam,
Expand All @@ -233,7 +243,7 @@ def delete(self, *args, **kwargs):
profile.save()
return super(RelayAddress, self).delete(*args, **kwargs)

def make_relay_address(user_profile, num_tries=0, domain=DOMAIN_DEFAULT):
def make_relay_address(user_profile, num_tries=0, domain=DEFAULT_DOMAIN):
if (
user_profile.at_max_free_aliases
and not user_profile.has_unlimited
Expand All @@ -244,7 +254,9 @@ def make_relay_address(user_profile, num_tries=0, domain=DOMAIN_DEFAULT):
)
if num_tries >= 5:
raise CannotMakeAddressException
relay_address = RelayAddress.objects.create(user=user_profile.user, domain=domain)
# only use the numerical value of the domain when creating the alias
domain_numerical = get_domain_numerical(domain)
relay_address = RelayAddress.objects.create(user=user_profile.user, domain=domain_numerical)
address_contains_badword = has_bad_words(relay_address.address)
address_already_deleted = DeletedAddress.objects.filter(
address_hash=address_hash(relay_address.address, domain=domain)
Expand All @@ -255,6 +267,10 @@ def make_relay_address(user_profile, num_tries=0, domain=DOMAIN_DEFAULT):
return RelayAddress.make_relay_address(user_profile, num_tries, domain)
return relay_address

@property
def domain_value(self):
return DOMAINS.get(self.get_domain_display())


class DeletedAddress(models.Model):
address_hash = models.CharField(max_length=64, db_index=True)
Expand Down
32 changes: 29 additions & 3 deletions emails/tests/models_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@

from django.conf import settings
from django.contrib.auth.models import User
from django.test import TestCase
from django.test import (
override_settings,
TestCase,
)

from allauth.socialaccount.models import SocialAccount

Expand All @@ -18,13 +21,16 @@
CannotMakeSubdomainException,
DeletedAddress,
DomainAddress,
get_domain_numerical,
has_bad_words,
NOT_PREMIUM_USER_ERR_MSG,
Profile,
RelayAddress,
TRY_DIFFERENT_VALUE_ERR_MSG,
)

TEST_DOMAINS = {'RELAY_FIREFOX_DOMAIN': 'default.com', 'MOZMAIL_DOMAIN': 'test.com'}


class MiscEmailModelsTest(TestCase):
def test_has_bad_words_with_bad_words(self):
Expand All @@ -50,6 +56,11 @@ def test_address_hash_with_additional_domain(self):
expected_hash = sha256(f'{address}@{test_domain}'.encode('utf-8')).hexdigest()
assert address_hash(address, domain=test_domain) == expected_hash

@patch('emails.models.DOMAINS', TEST_DOMAINS)
def test_get_domain_numerical(self):
assert get_domain_numerical('default.com') == 1
assert get_domain_numerical('test.com') == 2


class RelayAddressTest(TestCase):
def setUp(self):
Expand Down Expand Up @@ -105,9 +116,13 @@ def test_make_relay_address_non_premium_user_cannot_pass_limit(self):
return
self.fail("Should have raised CannotMakeSubdomainException")

@override_settings(MOZMAIL_DOMAIN='test.com')
@patch('emails.models.DOMAINS', TEST_DOMAINS)
def test_make_relay_address_with_specified_domain(self):
relay_address = RelayAddress.make_relay_address(self.user_profile, domain='domain.com')
assert relay_address.domain == 'domain.com'
relay_address = RelayAddress.make_relay_address(self.user_profile, domain='test.com')
assert relay_address.domain == 2
assert relay_address.get_domain_display() == 'MOZMAIL_DOMAIN'
assert relay_address.domain_value == 'test.com'

def test_delete_adds_deleted_address_object(self):
relay_address = baker.make(RelayAddress)
Expand All @@ -120,6 +135,17 @@ def test_delete_adds_deleted_address_object(self):
).count()
assert deleted_count == 1

def test_delete_mozmail_deleted_address_object(self):
relay_address = baker.make(RelayAddress, domain=2)
address_hash = sha256(
f'{relay_address.address}@{relay_address.domain_value}'.encode('utf-8')
).hexdigest()
relay_address.delete()
deleted_count = DeletedAddress.objects.filter(
address_hash=address_hash
).count()
assert deleted_count == 1

# trigger a collision by making address_default always return 'aaaaaaaaa'
@patch.multiple('string', ascii_lowercase='a', digits='')
def test_make_relay_address_doesnt_make_dupe_of_deleted(self):
Expand Down
3 changes: 2 additions & 1 deletion privaterelay/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,8 @@ def _get_initial_middleware():
},
]

ADDITIONAL_DOMAINS = config('ADDITIONAL_DOMAINS', '', cast=str).split(',')
RELAY_FIREFOX_DOMAIN = config('RELAY_FIREFOX_DOMAIN', 'relay.firefox.com', cast=str)
MOZMAIL_DOMAIN = config('MOZMAIL_DOMAIN', 'mozmail.com', cast=str)
MAX_NUM_FREE_ALIASES = config('MAX_NUM_FREE_ALIASES', 5, cast=int)
PREMIUM_ENABLED = config('PREMIUM_ENABLED', default=False, cast=bool)
PREMIUM_PROD_ID = config('PREMIUM_PROD_ID', '', cast=str)
Expand Down
Empty file added privaterelay/tests/__init__.py
Empty file.

0 comments on commit 92dce9c

Please sign in to comment.