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