mirror of
https://github.com/zulip/zulip.git
synced 2025-11-07 07:23:22 +00:00
This commit removes the ability to configure different validity durations
for different types of confirmation links. I don't think the extra
configurability was worth the extra complexity, either for the user trying
to understand the settings, or for the developer trying to understand the
code.
The commit replaces all confirmation validity duration settings with a
single setting, settings.EMAIL_CONFIRMATION_DAYS.
The only setting it removes is settings.EMAIL_CHANGE_CONFIRMATION_DAYS,
which was introduced in 5bf83f9 and never advertised in prod_settings.py.
123 lines
4.8 KiB
Python
123 lines
4.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
# Copyright: (c) 2008, Jarek Zgoda <jarek.zgoda@gmail.com>
|
|
|
|
__revision__ = '$Id: models.py 28 2009-10-22 15:03:02Z jarek.zgoda $'
|
|
|
|
import re
|
|
|
|
from django.db import models
|
|
from django.core.urlresolvers import reverse
|
|
from django.conf import settings
|
|
from django.contrib.sites.models import Site
|
|
from django.contrib.contenttypes.models import ContentType
|
|
from django.contrib.contenttypes.fields import GenericForeignKey
|
|
from django.utils.timezone import now as timezone_now
|
|
|
|
from confirmation.util import get_status_field
|
|
from zerver.lib.send_email import send_email
|
|
from zerver.lib.utils import generate_random_token
|
|
from zerver.models import PreregistrationUser, EmailChangeStatus
|
|
from typing import Any, Dict, Optional, Text, Union
|
|
|
|
B16_RE = re.compile('^[a-f0-9]{40}$')
|
|
|
|
def generate_key():
|
|
# type: () -> Text
|
|
return generate_random_token(40)
|
|
|
|
class ConfirmationManager(models.Manager):
|
|
def confirm(self, confirmation_key):
|
|
# type: (str) -> Union[bool, PreregistrationUser, EmailChangeStatus]
|
|
if B16_RE.search(confirmation_key):
|
|
try:
|
|
confirmation = self.get(confirmation_key=confirmation_key)
|
|
except self.model.DoesNotExist:
|
|
return False
|
|
|
|
time_elapsed = timezone_now() - confirmation.date_sent
|
|
if time_elapsed.total_seconds() > settings.EMAIL_CONFIRMATION_DAYS * 24 * 3600:
|
|
return False
|
|
|
|
obj = confirmation.content_object
|
|
status_field = get_status_field(obj._meta.app_label, obj._meta.model_name)
|
|
setattr(obj, status_field, getattr(settings, 'STATUS_ACTIVE', 1))
|
|
obj.save()
|
|
return obj
|
|
return False
|
|
|
|
def get_link_for_object(self, obj, host=None):
|
|
# type: (Union[ContentType, int], Optional[str]) -> Text
|
|
key = generate_key()
|
|
self.create(content_object=obj, date_sent=timezone_now(), confirmation_key=key)
|
|
return self.get_activation_url(key, host=host)
|
|
|
|
def get_activation_url(self, confirmation_key, host=None):
|
|
# type: (Text, Optional[str]) -> Text
|
|
if host is None:
|
|
host = settings.EXTERNAL_HOST
|
|
return u'%s%s%s' % (settings.EXTERNAL_URI_SCHEME,
|
|
host,
|
|
reverse('confirmation.views.confirm',
|
|
kwargs={'confirmation_key': confirmation_key}))
|
|
|
|
class EmailChangeConfirmationManager(ConfirmationManager):
|
|
def get_activation_url(self, key, host=None):
|
|
# type: (Text, Optional[str]) -> Text
|
|
if host is None:
|
|
# This will raise exception if the key doesn't exist.
|
|
host = self.get(confirmation_key=key).content_object.realm.host
|
|
return u'%s%s%s' % (settings.EXTERNAL_URI_SCHEME,
|
|
host,
|
|
reverse('zerver.views.user_settings.confirm_email_change',
|
|
kwargs={'confirmation_key': key}))
|
|
|
|
class Confirmation(models.Model):
|
|
content_type = models.ForeignKey(ContentType)
|
|
object_id = models.PositiveIntegerField()
|
|
content_object = GenericForeignKey('content_type', 'object_id')
|
|
date_sent = models.DateTimeField('sent')
|
|
confirmation_key = models.CharField('activation key', max_length=40)
|
|
|
|
objects = ConfirmationManager()
|
|
|
|
class Meta(object):
|
|
verbose_name = 'confirmation email'
|
|
verbose_name_plural = 'confirmation emails'
|
|
|
|
def __unicode__(self):
|
|
# type: () -> Text
|
|
return 'confirmation email for %s' % (self.content_object,)
|
|
|
|
class EmailChangeConfirmation(Confirmation):
|
|
class Meta(object):
|
|
proxy = True
|
|
|
|
objects = EmailChangeConfirmationManager()
|
|
|
|
# Conirmation pathways for which there is no content_object that we need to
|
|
# keep track of.
|
|
|
|
def check_key_is_valid(creation_key):
|
|
# type: (Text) -> bool
|
|
if not RealmCreationKey.objects.filter(creation_key=creation_key).exists():
|
|
return False
|
|
days_sofar = (timezone_now() - RealmCreationKey.objects.get(creation_key=creation_key).date_created).days
|
|
# Realm creation link expires after settings.REALM_CREATION_LINK_VALIDITY_DAYS
|
|
if days_sofar <= settings.REALM_CREATION_LINK_VALIDITY_DAYS:
|
|
return True
|
|
return False
|
|
|
|
def generate_realm_creation_url():
|
|
# type: () -> Text
|
|
key = generate_key()
|
|
RealmCreationKey.objects.create(creation_key=key, date_created=timezone_now())
|
|
return u'%s%s%s' % (settings.EXTERNAL_URI_SCHEME,
|
|
settings.EXTERNAL_HOST,
|
|
reverse('zerver.views.create_realm',
|
|
kwargs={'creation_key': key}))
|
|
|
|
class RealmCreationKey(models.Model):
|
|
creation_key = models.CharField('activation key', max_length=40)
|
|
date_created = models.DateTimeField('created', default=timezone_now)
|