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