1from datetime import timedelta 2 3from django.db import models 4from django.db.models import Q 5from django.utils import timezone 6 7from . import app_settings 8 9 10class EmailAddressManager(models.Manager): 11 12 def add_email(self, request, user, email, 13 confirm=False, signup=False): 14 email_address, created = self.get_or_create( 15 user=user, email__iexact=email, defaults={"email": email} 16 ) 17 18 if created and confirm: 19 email_address.send_confirmation(request, signup=signup) 20 21 return email_address 22 23 def get_primary(self, user): 24 try: 25 return self.get(user=user, primary=True) 26 except self.model.DoesNotExist: 27 return None 28 29 def get_users_for(self, email): 30 # this is a list rather than a generator because we probably want to 31 # do a len() on it right away 32 return [address.user for address in self.filter(verified=True, 33 email__iexact=email)] 34 35 def fill_cache_for_user(self, user, addresses): 36 """ 37 In a multi-db setup, inserting records and re-reading them later 38 on may result in not being able to find newly inserted 39 records. Therefore, we maintain a cache for the user so that 40 we can avoid database access when we need to re-read.. 41 """ 42 user._emailaddress_cache = addresses 43 44 def get_for_user(self, user, email): 45 cache_key = '_emailaddress_cache' 46 addresses = getattr(user, cache_key, None) 47 if addresses is None: 48 ret = self.get(user=user, 49 email__iexact=email) 50 # To avoid additional lookups when e.g. 51 # EmailAddress.set_as_primary() starts touching self.user 52 ret.user = user 53 return ret 54 else: 55 for address in addresses: 56 if address.email.lower() == email.lower(): 57 return address 58 raise self.model.DoesNotExist() 59 60 61class EmailConfirmationManager(models.Manager): 62 63 def all_expired(self): 64 return self.filter(self.expired_q()) 65 66 def all_valid(self): 67 return self.exclude(self.expired_q()) 68 69 def expired_q(self): 70 sent_threshold = timezone.now() \ 71 - timedelta(days=app_settings.EMAIL_CONFIRMATION_EXPIRE_DAYS) 72 return Q(sent__lt=sent_threshold) 73 74 def delete_expired_confirmations(self): 75 self.all_expired().delete() 76