aboutsummaryrefslogtreecommitdiffstats
path: root/97suifangqa/apps/sfaccount/models.py
diff options
context:
space:
mode:
Diffstat (limited to '97suifangqa/apps/sfaccount/models.py')
-rw-r--r--97suifangqa/apps/sfaccount/models.py172
1 files changed, 172 insertions, 0 deletions
diff --git a/97suifangqa/apps/sfaccount/models.py b/97suifangqa/apps/sfaccount/models.py
new file mode 100644
index 0000000..bb1fe29
--- /dev/null
+++ b/97suifangqa/apps/sfaccount/models.py
@@ -0,0 +1,172 @@
+# -*- coding: utf-8 -*-
+
+from django.conf import settings
+from django.db import models
+from django.contrib import admin
+from django.contrib.auth.models import User
+from django.utils.hashcompat import sha_constructor
+from django.utils.timezone import utc
+from django.template.loader import render_to_string
+
+from sfaccount.tasks import send_mail
+
+import re
+import random
+import datetime
+
+
+# SHA1 Hash regex
+SHA1 = re.compile('^[a-f0-9]{40}$')
+
+
+class AccountManager(models.Manager): # {{{
+ """
+ custom manager for 'Account' model
+ """
+ def activate(self, activation_key):
+ """
+ validate an activation key and activate the corresponding
+ 'User' if valid.
+
+ if the key is valid and not expired, return the 'Account'
+ if the key is invalid or expired, return 'False'
+ if the key is valid but the 'User' is already activated,
+ return 'False'
+
+ reset the key string to prevent reactivation of an account
+ which has been deactivated by the admin
+ """
+ if SHA1.search(activation_key):
+ try:
+ account = self.get(activation_key=activation_key)
+ except self.model.DoesNotExist:
+ return False
+ if not account.activation_key_expired():
+ user = account.user
+ user.is_active = True
+ user.save()
+ account.activation_key = self.model.ACTIVATED
+ account.save()
+ return account
+ return False
+
+ def create_inactive_account(self, username, email, password,
+ send_email=True):
+ """
+ create a new, *local*, inactive 'User',
+ and generate an 'Account' and
+ email the activation key. return the new 'User'
+
+ the activation key is a SHA1 hash, generated from
+ a combination of the 'username' and a random slat
+ """
+ new_user = User.objects.create_user(username, email, password)
+ new_user.is_active = False
+ new_user.save()
+ # create corresponding 'Account'
+ salt = sha_constructor(str(random.random())).hexdigest()[:5]
+ activation_key = sha_constructor(salt+username).hexdigest()
+ new_account = self.create(user=new_user, is_social=False,
+ activation_key=activation_key)
+ new_account.save()
+ # send email
+ if send_email:
+ new_account.send_activation_email()
+ return new_account
+
+ def delete_expired_accounts(self):
+ """
+ Remove expired instances of 'Account's and their
+ associated 'User's.
+ """
+ for account in self.all():
+ if account.activation_key_expired():
+ user = account.user
+ if not user.is_active:
+ user.delete()
+ account.delete()
+# }}}
+
+
+class Account(models.Model): # {{{
+ """
+ Account model for 97suifang
+ """
+ ACTIVATED = u'ALREADY_ACTIVATED'
+
+ user = models.OneToOneField(User, related_name="account")
+ # username -> user.username
+ # date_joined -> user.date_joined
+ screen_name = models.CharField(u"昵称", max_length=30,
+ null=True, blank=True)
+ avatar = models.ImageField(u"头像", upload_to="uploads/avatars/",
+ null=True, blank=True)
+ # if social account
+ is_social = models.BooleanField(default=False)
+ # activation (SHA1 hash)
+ activation_key = models.CharField(u"激活密钥", max_length=40)
+
+ objects = AccountManager()
+
+ class Meta:
+ verbose_name_plural = u"账户信息"
+
+ def __unicode__(self):
+ if self.is_social:
+ type = u"social"
+ else:
+ type = u"local"
+ if self.user.is_active:
+ state = u"activated"
+ else:
+ state = u"nonactivated"
+ #
+ return u'< Account: %s, %s, %s >' % (self.user.username,
+ type, state)
+
+ def activation_key_expired(self):
+ """
+ determine whether the activation key has expired
+
+ Key expiration is determined by a two-step process:
+
+ 1. If the user has already activated, the key will have been
+ reset to the string constant ``ACTIVATED``. Re-activating
+ is not permitted, and so this method returns ``True`` in
+ this case.
+
+ 2. Otherwise, the date the user signed up is incremented by
+ the number of days specified in the setting
+ ``ACCOUNT_ACTIVATION_DAYS`` (which should be the number of
+ days after signup during which a user is allowed to
+ activate their account); if the result is less than or
+ equal to the current date, the key has expired and this
+ method returns ``True``.
+ """
+ expiration_days = datetime.timedelta(
+ days=settings.ACCOUNT_ACTIVATION_DAYS)
+ now_utc = datetime.datetime.utcnow().replace(tzinfo=utc)
+ return self.user.is_active or (
+ self.user.date_joined + expiration_days <= now_utc)
+
+ def send_activation_email(self):
+ """
+ send an activation email to the newly registered user
+ """
+ ctx_dict = {
+ 'username': self.user.username,
+ 'activation_key': self.activation_key,
+ 'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS,
+ }
+ subject = render_to_string('sfaccount/activation_email_subject.txt', ctx_dict)
+ subject = ''.join(subject.splitlines())
+ body_text = render_to_string('sfaccount/activation_email_body.txt', ctx_dict).encode('utf-8')
+ to = self.user.email
+ # send email
+ send_mail.delay(to, subject, body_text, None)
+# }}}
+
+
+admin.site.register([Account])
+
+# vim: set ts=4 sw=4 tw=0 fenc=utf-8 ft=python: #