mirror of https://github.com/zulip/zulip.git
Include third-party django-confirmation library.
Taken from http://code.google.com/p/django-confirmation/. Code is under the BSD 3-clause license. (imported from commit cfb5a511097fe14fba7f1bcea62dfa25cfb58622)
This commit is contained in:
parent
5556bdd0a1
commit
b801b50c26
|
@ -0,0 +1,3 @@
|
||||||
|
=============================
|
||||||
|
Django Confirmation Changelog
|
||||||
|
=============================
|
|
@ -0,0 +1,12 @@
|
||||||
|
To install django-confirmation, run the following command inside this
|
||||||
|
directory:
|
||||||
|
|
||||||
|
python setup.py install
|
||||||
|
|
||||||
|
You can also just copy the included ``confirmation`` directory somewhere
|
||||||
|
on your Python path, or symlink to it from somewhere on your Python path;
|
||||||
|
this is useful if you're working from a Subversion checkout.
|
||||||
|
|
||||||
|
This application requires Python 2.3 or later, and Django 1.0 or later.
|
||||||
|
You can obtain Python from http://www.python.org/ and Django from
|
||||||
|
http://www.djangoproject.com/.
|
|
@ -0,0 +1,28 @@
|
||||||
|
Copyright (c) 2008, Jarek Zgoda <jarek.zgoda@gmail.com>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer in the documentation and/or other materials provided
|
||||||
|
with the distribution.
|
||||||
|
* Neither the name of the author nor the names of other
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,10 @@
|
||||||
|
===================
|
||||||
|
Django Confirmation
|
||||||
|
===================
|
||||||
|
|
||||||
|
This is a generic object confirmation system for Django applications.
|
||||||
|
|
||||||
|
For installation instructions, see the file "INSTALL.txt" in this
|
||||||
|
directory; for instructions on how to use this application, and on
|
||||||
|
what it provides, see the file "overview.txt" in the "docs/"
|
||||||
|
directory.
|
|
@ -0,0 +1,24 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright: (c) 2008, Jarek Zgoda <jarek.zgoda@gmail.com>
|
||||||
|
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
# copy of this software and associated documentation files (the
|
||||||
|
# "Software"), to deal in the Software without restriction, including
|
||||||
|
# without limitation the rights to use, copy, modify, merge, publish, dis-
|
||||||
|
# tribute, sublicense, and/or sell copies of the Software, and to permit
|
||||||
|
# persons to whom the Software is furnished to do so, subject to the fol-
|
||||||
|
# lowing conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included
|
||||||
|
# in all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
|
||||||
|
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||||
|
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
# IN THE SOFTWARE.
|
||||||
|
|
||||||
|
VERSION = (0, 9, 'pre')
|
|
@ -0,0 +1,13 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright: (c) 2008, Jarek Zgoda <jarek.zgoda@gmail.com>
|
||||||
|
|
||||||
|
__revision__ = '$Id: admin.py 3 2008-11-18 07:33:52Z jarek.zgoda $'
|
||||||
|
|
||||||
|
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
from confirmation.models import Confirmation
|
||||||
|
|
||||||
|
|
||||||
|
admin.site.register(Confirmation)
|
|
@ -0,0 +1,17 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright: (c) 2008, Jarek Zgoda <jarek.zgoda@gmail.com>
|
||||||
|
|
||||||
|
__revision__ = '$Id: cleanupconfirmation.py 5 2008-11-18 09:10:12Z jarek.zgoda $'
|
||||||
|
|
||||||
|
|
||||||
|
from django.core.management.base import NoArgsCommand
|
||||||
|
|
||||||
|
from confirmation.models import Confirmation
|
||||||
|
|
||||||
|
|
||||||
|
class Command(NoArgsCommand):
|
||||||
|
help = 'Delete expired confirmations from database'
|
||||||
|
|
||||||
|
def handle_noargs(self, **options):
|
||||||
|
Confirmation.objects.delete_expired_confirmations()
|
|
@ -0,0 +1,103 @@
|
||||||
|
# -*- 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 os
|
||||||
|
import re
|
||||||
|
import datetime
|
||||||
|
from hashlib import sha1
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
|
from django.core.mail import send_mail
|
||||||
|
from django.conf import settings
|
||||||
|
from django.template import loader, Context
|
||||||
|
from django.contrib.sites.models import Site
|
||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
from django.contrib.contenttypes import generic
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from confirmation.util import get_status_field
|
||||||
|
|
||||||
|
try:
|
||||||
|
import mailer
|
||||||
|
send_mail = mailer.send_mail
|
||||||
|
except ImportError:
|
||||||
|
# no mailer app present, stick with default
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
SHA1_RE = re.compile('^[a-f0-9]{40}$')
|
||||||
|
|
||||||
|
|
||||||
|
class ConfirmationManager(models.Manager):
|
||||||
|
|
||||||
|
def confirm(self, confirmation_key):
|
||||||
|
if SHA1_RE.search(confirmation_key):
|
||||||
|
try:
|
||||||
|
confirmation = self.get(confirmation_key=confirmation_key)
|
||||||
|
except self.model.DoesNotExist:
|
||||||
|
return False
|
||||||
|
if not confirmation.key_expired():
|
||||||
|
obj = confirmation.content_object
|
||||||
|
status_field = get_status_field(obj._meta.app_label, obj._meta.module_name)
|
||||||
|
setattr(obj, status_field, getattr(settings, 'STATUS_ACTIVE', 1))
|
||||||
|
obj.save()
|
||||||
|
return obj
|
||||||
|
return False
|
||||||
|
|
||||||
|
def send_confirmation(self, obj, email_address):
|
||||||
|
confirmation_key = sha1(str(os.urandom(12)) + str(email_address)).hexdigest()
|
||||||
|
current_site = Site.objects.get_current()
|
||||||
|
activate_url = u'http://%s%s' % (current_site.domain,
|
||||||
|
reverse('confirmation.views.confirm', kwargs={'confirmation_key': confirmation_key}))
|
||||||
|
context = Context({
|
||||||
|
'activate_url': activate_url,
|
||||||
|
'current_site': current_site,
|
||||||
|
'confirmation_key': confirmation_key,
|
||||||
|
'target': obj,
|
||||||
|
'days': getattr(settings, 'EMAIL_CONFIRMATION_DAYS', 10),
|
||||||
|
})
|
||||||
|
templates = [
|
||||||
|
'confirmation/%s_confirmation_email_subject.txt' % obj._meta.module_name,
|
||||||
|
'confirmation/confirmation_email_subject.txt',
|
||||||
|
]
|
||||||
|
template = loader.select_template(templates)
|
||||||
|
subject = template.render(context).strip().replace(u'\n', u' ') # no newlines, please
|
||||||
|
templates = [
|
||||||
|
'confirmation/%s_confirmation_email_body.txt' % obj._meta.module_name,
|
||||||
|
'confirmation/confirmation_email_body.txt',
|
||||||
|
]
|
||||||
|
template = loader.select_template(templates)
|
||||||
|
body = template.render(context)
|
||||||
|
send_mail(subject, body, settings.DEFAULT_FROM_EMAIL, [email_address])
|
||||||
|
return self.create(content_object=obj, date_sent=datetime.datetime.now(), confirmation_key=confirmation_key)
|
||||||
|
|
||||||
|
def delete_expired_confirmations(self):
|
||||||
|
for confirmation in self.all():
|
||||||
|
if confirmation.key_expired():
|
||||||
|
confirmation.delete()
|
||||||
|
|
||||||
|
|
||||||
|
class Confirmation(models.Model):
|
||||||
|
content_type = models.ForeignKey(ContentType)
|
||||||
|
object_id = models.PositiveIntegerField()
|
||||||
|
content_object = generic.GenericForeignKey('content_type', 'object_id')
|
||||||
|
date_sent = models.DateTimeField(_('sent'))
|
||||||
|
confirmation_key = models.CharField(_('activation key'), max_length=40)
|
||||||
|
|
||||||
|
objects = ConfirmationManager()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _('confirmation email')
|
||||||
|
verbose_name_plural = _('confirmation emails')
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return _('confirmation email for %s') % self.content_object
|
||||||
|
|
||||||
|
def key_expired(self):
|
||||||
|
expiration_date = self.date_sent + datetime.timedelta(days=getattr(settings, 'EMAIL_CONFIRMATION_DAYS', 10))
|
||||||
|
return expiration_date <= datetime.datetime.now()
|
||||||
|
key_expired.boolean = True
|
|
@ -0,0 +1,12 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright: (c) 2008, Jarek Zgoda <jarek.zgoda@gmail.com>
|
||||||
|
|
||||||
|
__revision__ = '$Id: settings.py 12 2008-11-23 19:38:52Z jarek.zgoda $'
|
||||||
|
|
||||||
|
EMAIL_CONFIRMATION_DAYS = 10
|
||||||
|
|
||||||
|
STATUS_ACTIVE = 1
|
||||||
|
|
||||||
|
STATUS_FIELDS = {
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
# Dynamically calculate the version based on confirmation.VERSION.
|
||||||
|
version_tuple = __import__('confirmation').VERSION
|
||||||
|
if version_tuple[2] is not None:
|
||||||
|
version = "%d.%d_%s" % version_tuple
|
||||||
|
else:
|
||||||
|
version = "%d.%d" % version_tuple[:2]
|
||||||
|
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name = 'django-confirmation',
|
||||||
|
version = version,
|
||||||
|
description = 'Generic object confirmation for Django',
|
||||||
|
author = 'Jarek Zgoda',
|
||||||
|
author_email = 'jarek.zgoda@gmail.com',
|
||||||
|
url = 'http://code.google.com/p/django-confirmation/',
|
||||||
|
license = 'New BSD License',
|
||||||
|
packages = find_packages(),
|
||||||
|
classifiers = [
|
||||||
|
'Development Status :: 4 - Beta',
|
||||||
|
'Environment :: Web Environment',
|
||||||
|
'Framework :: Django',
|
||||||
|
'Intended Audience :: Developers',
|
||||||
|
'License :: OSI Approved :: BSD License',
|
||||||
|
'Operating System :: OS Independent',
|
||||||
|
'Programming Language :: Python',
|
||||||
|
'Topic :: Utilities',
|
||||||
|
],
|
||||||
|
zip_safe = False,
|
||||||
|
install_requires = [
|
||||||
|
'django>=1.0',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright: (c) 2008, Jarek Zgoda <jarek.zgoda@gmail.com>
|
||||||
|
|
||||||
|
__revision__ = '$Id: urls.py 3 2008-11-18 07:33:52Z jarek.zgoda $'
|
||||||
|
|
||||||
|
|
||||||
|
from django.conf.urls.defaults import *
|
||||||
|
|
||||||
|
from confirmation.views import confirm
|
||||||
|
|
||||||
|
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
(r'^(?P<confirmation_key>\w+)/$', confirm),
|
||||||
|
)
|
|
@ -0,0 +1,12 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright: (c) 2008, Jarek Zgoda <jarek.zgoda@gmail.com>
|
||||||
|
|
||||||
|
__revision__ = '$Id: util.py 3 2008-11-18 07:33:52Z jarek.zgoda $'
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
def get_status_field(app_label, model_name):
|
||||||
|
model = '%s.%s' % (app_label, model_name)
|
||||||
|
mapping = getattr(settings, 'STATUS_FIELDS', {})
|
||||||
|
return mapping.get(model, 'status')
|
|
@ -0,0 +1,39 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright: (c) 2008, Jarek Zgoda <jarek.zgoda@gmail.com>
|
||||||
|
|
||||||
|
__revision__ = '$Id: views.py 21 2008-12-05 09:21:03Z jarek.zgoda $'
|
||||||
|
|
||||||
|
|
||||||
|
from django.shortcuts import render_to_response
|
||||||
|
from django.template import RequestContext
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
from confirmation.models import Confirmation
|
||||||
|
|
||||||
|
|
||||||
|
def confirm(request, confirmation_key):
|
||||||
|
confirmation_key = confirmation_key.lower()
|
||||||
|
obj = Confirmation.objects.confirm(confirmation_key)
|
||||||
|
confirmed = True
|
||||||
|
if not obj:
|
||||||
|
# confirmation failed
|
||||||
|
confirmed = False
|
||||||
|
try:
|
||||||
|
# try to get the object we was supposed to confirm
|
||||||
|
obj = Confirmation.objects.get(confirmation_key=confirmation_key)
|
||||||
|
except Confirmation.DoesNotExist:
|
||||||
|
pass
|
||||||
|
ctx = {
|
||||||
|
'object': obj,
|
||||||
|
'confirmed': confirmed,
|
||||||
|
'days': getattr(settings, 'EMAIL_CONFIRMATION_DAYS', 10),
|
||||||
|
}
|
||||||
|
templates = [
|
||||||
|
'confirmation/confirm.html',
|
||||||
|
]
|
||||||
|
if obj:
|
||||||
|
# if we have an object, we can use specific template
|
||||||
|
templates.insert(0, 'confirmation/confirm_%s.html' % obj._meta.module_name)
|
||||||
|
return render_to_response(templates, ctx,
|
||||||
|
context_instance=RequestContext(request))
|
Loading…
Reference in New Issue