Commits

offline committed 13014e5

first commit

  • Participants
  • Parent commits 14979eb

Comments (0)

Files changed (8)

 .*\.pyc
+django_auth.egg-info
+"""
+Django application
+"""
+from django.db import models
+from django.contrib.auth.models import User
+
+from annoying.fields import AutoOneToOneField
+
+import auth
+from auth.utils import unicode_urlencode, generate_hash
+
+User.username = models.CharField(max_length=30)
+
+
+class Profile(models.Model):
+    user = AutoOneToOneField(User, primary_key=True)
+    country = models.CharField(max_length=50, blank=True)
+    about = models.TextField(blank=True)
+    
+    def get_gravatar(self, size=None):
+        """
+        Get gravatar image src with specified size (width, height), or use default
+        """
+        if not size:
+            size = auth.settings.GRAVATAR_SIZE
+        auth.settings.GRAVATAR_URL += unicode_urlencode({
+                                    'gravatar_id': generate_hash(self.user.email.lower()),
+                                    'size': size,
+                                    'default': auth.settings.GRAVATAR_TYPE,
+                                    })
+        return auth.settings.GRAVATAR_URL
+
+    
+    def __unicode__(self):
+        return self.user.username
+
+
+
+class Confirmation(models.Model):
+    """
+    Can be used for user activation, but also for
+    other purposes where confirmation is required.
+    """
+    user = models.ForeignKey(User)
+    key = models.CharField(max_length=32)
+    confirmation_type = models.IntegerField(default=1)
+
+    def __unicode__(self):
+        """
+        return:
+
+        vasya@pupkin: 36799bbfa2d074b5ffc1e8a55fb7f539
+        """
+        return "%s: %s" % (self.user.email, self.key)
+
+
+import time
+
+from datetime import datetime, timedelta, date
+
+from django.conf import settings
+from django.contrib.auth.models import User
+from django.core.urlresolvers import reverse
+from django.contrib.auth.decorators import login_required
+from django.contrib.auth import proccess_login
+from django.shortcuts import get_object_or_404, redirect
+from django.utils.translation import ugettext as _
+from django.http import HttpResponseRedirect
+from django.db.models import Q
+
+from annoying.decorators import ajax_request
+from ninjapaginator.util import NinjaPaginator
+
+
+from auth.forms import RestorePasswordForm, NewPasswordForm, LoginForm, NewEmailForm, EditUserForm
+                          
+from auth.util import email_template, build_redirect_url
+from auth.models import Confirmation
+
+
+def message(request, msg, priority, redirect_name, args=None, kwargs=None):
+    """
+    Shortcut that prepare data for message view.
+    """
+    if auth.settings.MESSAGE_TYPE == 'flash':
+        request.flash[priority] = msg
+        return redirect(redirect_name, args=args, kwargs=kwargs)
+    return {'TEMPLATE': 'auth/message.html', 'message': msg}
+
+
+@render_to()
+def confirm(request):
+    """
+    Check confirmation key, proccess confirmation and delete key.
+    """
+    key = request.GET.get("key")
+    confirmation_type = int(request.GET.get("type", 1))
+    confirmation = get_object_or_404(Confirmation, key=key, confirmation_type=confirmation_type)
+    if confirmation_type == auth.settings.ACTIVATION_CONFIRMATION_TYPE:
+        user = confirmation.user
+        user.is_active = True
+        user.save()
+        if auth.settings.ACTIVATION_AUTO_LOGIN:
+            confirmation.user.backend = 'django.contrib.auth.backends.ModelBackend'
+            proccess_login(request, user)
+
+        activation.delete()
+        return message(request, _('Your account successfully activated'), 'success', 'show-user', args=[user.id])
+    elif confiramtion_type == auth.settings.PASSWORD_RESET_CONFIRMATION_TYPE:
+        confirmation.user.backend = 'django.contrib.auth.backends.ModelBackend'                                                                                  
+        proccess_login(request, confirmation.user)      
+        confirmation.delete()
+        return message(request, _("Now you can change your password"), "notice", "auth-reset-form")
+    else:
+        return auth.settings.CUSTOM_CONFIRMATION(request)
+
+
+@render_to('auth/registration.html')
+def registration(request):
+    """
+    Only anonymous users can view this page
+    Registration should be allowed in REGISTRATION_ALLOWED setting
+    """
+    if request.user.is_authenticated():
+        return message(request, _('You have to logout before registration'), 'notice', '/')
+
+    if not auth.settings.REGISTRATION_ALLOWED: 
+        request.flash['notice'] = 'Sorry. Registration is disabled.'
+        return message(request, _('We are sorry, but registration is disabled. Come back later'), 'notice', '/')
+
+    if request.POST:
+        form = auth.settings.REGISTRATION_FORM(request.POST)
+        if form.is_valid():
+            user = form.save()
+            if auth.settings.ACTIVATION_REQUIRED:
+                user.is_active = False
+            user.save()
+
+            if auth.settings.ACTIVATION_REQUIRED:
+                confirmation = Confirmation(user=user, key=generate_hash(), auth.settings.ACTIVATION_CONFIRMATION_TYPE)
+                confirmation.save()
+                url = request.build_absolute_uri(reverse('confirmation'))
+                url += '?key=%s&type=%s' % (confirmation.key, confirmation.confirmation_type)
+                params = {'domain': request.get_host(), 'email': user.email, 'url': url}
+                if email_template(user.email, 'account/mail/registration.txt', **params):
+                    return message(request, _("You have successfully registered. Check your inbox for email with activation link."), "success", "/")
+                else:
+                    user.delete()
+                    return message(request, _('The error was occuried while sending email with activation code. Account was not created. Please, try later.'), "error", "/")
+            else:
+                return message(request, _("You have successfully registered. You can login now"), "success", "login")
+
+    else:
+        form = auth.settings.REGISTRATION_FORM()
+    return {'form': form}
+
+
+@render_to('auth/reset_password.html')
+def reset_password(request):
+    if request.POST:
+        form = ResetPasswordForm(request.POST)
+        if form.is_valid():
+            user = User.objects.get(email=form.cleaned_data['email'].lower())
+            confirmation = Confirmation(user=user, key=generate_hash(), confirmation_type=PASSWORD_RESET_CONFIRMATION_TYPE)
+            confirmation.save()
+            url = request.build_redirect_url(reverse('auth-confirmation'))
+            url += '?key=%s&type=%s' % (confirmation.key, auth.settings.PASSWORD_RESET_CONFIRMATION_TYPE)
+            args = {'domain': request.get_host(), 'url': url}
+            if email_template(user.email, 'auth/mail/reset_password.txt', **args):
+                return message(request, _('Check your email please'), 'notice', '/')
+            else:
+                return message(request, _('Unfortunately we could not send you email in current time. Please, try later'), 'error', '/')
+    else:
+        form = RestorePasswordForm()
+    return {'form': form}
+
+
+@render_to('auth/login.html')
+def login(request):
+    if request.user.is_authenticated():
+        return message(request, _('You are already authenticated'), 'notice', '/')
+
+    if request.POST:
+        form = LoginForm(request.POST, request=request)
+        request.session['login_redirect_url'] = request.GET.get('next')
+        if form.is_valid():
+            redirect_url = build_redirect_url(request, auth.settings.LOGIN_REDIRECT_URL)
+            return message(request, _('You have successfully logged-in'), 'success', redirect_url)
+    else:
+        form = LoginForm(request=request)
+    return {'form': form}
+
+
+@login_required
+@render_to('account/new_password.html')
+def new_password(request):
+    if 'POST' == request.method:
+        form = NewPasswordForm(request.POST)
+    else:
+        form = NewPasswordForm()
+
+    if form.is_valid():
+        form.save(request.user)
+        request.flash['notice'] = _('Password was changed')
+        return HttpResponseRedirect("/")
+    return {'form': form}
+
+
+@render_to('account/message.html')
+def logout(request):
+    auth.logout(request)
+    request.flash['notice'] = "You have been logged out"
+    return HttpResponseReload(request)
+
+
+@render_to('account/edit_user.html')
+def edit_user(request, user_id):
+    user = get_object_or_404(User, pk=user_id)
+    if not request.user.is_authenticated() or user != request.user and not request.user.is_staff:
+        return HttpResponseReload(request)
+    if request.POST:
+        form = EditUserForm(user, request.POST, request.FILES)
+        if form.is_valid():
+            form.save()
+            request.flash['notice'] = "User details successfully changed"
+            return HttpResponseRedirect(reverse('show-user', args=[user.id]))
+    else:
+        initial = {'username': user.username, 
+                    'country': user.profile.country,
+                    'jabber': user.profile.jabber,
+                    'about': user.profile.about}
+        form = EditUserForm(user, initial=initial)
+    return {'form': form, 'user': user}
+
+
+
+@render_to('auth/profile.html')
+def show_user(request, user_id):
+    """
+    Show user profile 
+    """
+    
+    user = get_object_or_404(User, pk=user_id)
+    return {'user': user}
+
+ 
+
+
+@render_to('account/users.html')
+@NinjaPaginator(style='filmfeed', per_page=16) 
+def users(request):
+    users = User.objects.all()
+    users = order_by(request, users)
+    return {'object_list': users}
+
+from django import forms
+from django.contrib.auth.models import User
+from django.contrib.auth import authenticate, login
+from django.utils.translation import ugettext as _
+from django.template import loader
+
+from annoying.functions import get_object_or_None
+from annoying.decorators import autostrip
+
+from auth.models import Confirmation
+
+
+
+class UsernameField(forms.CharField):
+    """
+    Form field for username handling.
+    """
+
+    def __init__(self, *args, **kwargs):
+        super(UsernameField, self).__init__(*args, **kwargs)
+        self.label = _(u'Login')
+
+
+    def clean(self, value):
+        super(UsernameField, self).clean(value)
+
+        if len(value) < auth.settings.USERNAME_MIN_LENGTH:
+            raise forms.ValidationError(_(u'Login length is less than %(min)d') % {'min': auth.settings.USERNAME_MIN_LENGTH})
+        if len(value) > auth.settings.USERNAME_MAX_LENGTH:
+            raise forms.ValidationError(_(u'Login length is more than %(max)d') % {'max': auth.settings.USERNAME_MAX_LENGTH})
+        if not auth.settings.USERNAME_REGEX.match(value):
+            raise forms.ValidationError(_(u'Login contains restricted symbols'))
+
+        try:
+            User.objects.get(username__exact=value)
+        except User.DoesNotExist:
+            return value
+        else:
+            raise forms.ValidationError(_(u'This login already registered'))
+
+
+class PasswordField(forms.CharField):
+    """
+    Form field for password handling.
+    """
+
+    def __init__(self, *args, **kwargs):
+        super(PasswordField, self).__init__(*args, **kwargs)
+        self.widget = forms.PasswordInput(attrs=auth.settings.PASSWORD_FIELD_ATTRIBUTES)
+        self.help_text = ''
+
+
+    def clean(self, value):
+        super(PasswordField, self).clean(value)
+        if len(value) < auth.settings.PASSWORD_MIN_LENGTH:
+            raise forms.ValidationError(_(u'Password length is less than %(min)d') % {'min': PASSWORD_MIN_LENGTH})
+        if len(value) > auth.settings.PASSWORD_MAX_LENGTH:
+            raise forms.ValidationError(_(u'Password length is more than %(max)d') % {'max': PASSWORD_MAX_LENGTH})
+        return value
+
+
+class RegistrationForm(forms.Form):
+    username = forms.CharField(label=_('Nickname'), max_length=30)
+    email = forms.EmailField(label=_('Email'))
+    password = PasswordField(label=_('Password'))
+    password_dup = PasswordField(label=_('Password (confirmation)'))
+
+    
+    def clean_email(self):
+        #return self.cleaned_data.get('email','')
+        try:
+            User.objects.get(email__exact=self.cleaned_data['email'].lower())
+        except User.DoesNotExist:
+            return self.cleaned_data['email']
+        except KeyError:
+            pass
+        else:
+            raise forms.ValidationError(_(u'This email already registered'))
+
+    
+    def clean(self):
+        pwd1 = self.cleaned_data.get('password')
+        pwd2 = self.cleaned_data.get('password_dup')
+        if pwd1 and pwd2:
+            if pwd1 != pwd2:
+                raise forms.ValidationError(_(u'Passwords do not match'))
+        return self.cleaned_data
+
+
+    def save(self):
+        username = self.cleaned_data['username']
+        email = self.cleaned_data['email'].lower()
+        password = self.cleaned_data['password']
+        user = User.objects.create_user(username, email, password=password)
+        return user
+
+RegistrationForm = autostrip(RegistrationForm)
+
+
+class RestorePasswordForm(forms.Form):
+    email = forms.EmailField(label=_('Email'), widget=forms.TextInput(attrs={'class': 'field_input'}))
+
+    def clean_email(self):
+        if 'email' in self.cleaned_data:
+            email = self.cleaned_data['email'].lower()
+            if User.objects.filter(email=email).count():
+                return email
+            else:
+                raise forms.ValidationError(_(u'This email is not registered'))
+
+
+RestorePasswordForm = autostrip(RestorePasswordForm)
+
+
+class LoginForm(forms.Form):
+    email = forms.EmailField(label=_('Email'))
+    password = forms.CharField(label=_('Password'), widget=forms.PasswordInput)
+
+    def __init__(self, *args, **kwargs):
+        self.request = kwargs.pop('request')
+        self.base_fields['email'].help_text = ''
+        #self.base_fields['password'].widget = forms.PasswordInput()
+        self.base_fields['password'].help_text = ''
+        super(LoginForm, self).__init__(*args, **kwargs)
+
+
+    def clean(self):
+        super(LoginForm, self).clean()
+        if self.is_valid():
+            email = self.cleaned_data['email'].lower()
+            password = self.cleaned_data['password']
+            user = get_object_or_None(User, email=email)
+            if user and  user.check_password(password):
+                if user.is_active:
+                    user.backend = 'django.contrib.auth.backends.ModelBackend'
+                    login(self.request, user)
+                    return self.cleaned_data
+                else:
+                    raise forms.ValidationError(_(u'Your account is not active. Please activate it.'))
+            else:
+                raise forms.ValidationError(_(u'Incorrect email or password'))
+
+LoginForm = autostrip(LoginForm)
+
+
+class NewPasswordForm(forms.Form):
+    """
+    Form for changing user's password.
+    """
+
+    password = PasswordField(label=_(u'Password'))
+    password_confirmation = PasswordField(label=_(u'Password (confirmation)'))
+
+
+
+    def clean_password_confirmation(self):
+        pass1 = self.cleaned_data['password']
+        pass2 = self.cleaned_data['password_confirmation']
+        if pass1 != pass2:
+            raise forms.ValidationError(_(u'The passwords do not match'))
+        else:
+            return pass1
+
+
+    def save(self, user):
+        user.set_password(self.cleaned_data['password'])
+        user.save()
+        return user
+
+NewPasswordForm = autostrip(NewPasswordForm)
+
+
+class NewEmailForm(forms.Form):
+    """
+    Form for email chanage.
+    """
+
+    email = forms.EmailField(label=_(u'New email'))
+
+    def save(self):
+        pass
+
+
+class EditUserForm(forms.Form):
+    def __init__(self, user, *args, **kwargs):
+        super(EditUserForm, self).__init__(*args, **kwargs)
+        self.user = user
+
+    username = forms.CharField(widget=forms.TextInput(attrs={'class':'field_input'}))
+    country = forms.CharField(widget=forms.TextInput(attrs={'class':'field_input'}), required=False)
+    jabber = forms.EmailField(widget=forms.TextInput(attrs={'class':'field_input'}), required=False)
+    about = forms.CharField(widget=forms.Textarea(attrs={'class':'field_input f130', 'style': 'height: 250px'}), required=False)
+
+
+
+    def save(self):
+        user = self.user
+        profile = user.profile
+        user.username = self.cleaned_data['username']
+        profile.country = self.cleaned_data['country']
+        profile.jabber = self.cleaned_data['jabber']
+        profile.about = self.cleaned_data['about']
+        user.save()
+        profile.save()
+        return user
+
+EditUserForm = autostrip(EditUserForm)
+from annoying.functions import get_config
+
+
+MESSAGE_TYPE = get_config("MESSAGE_TYPE", "flash")
+CUSTOM_CONFIRMATION = get_config("CUSTOM_CONFIRMATION", None) # custom confirmation function
+REGISTRATION_ALOWED = get_config("REGISTRATION_ALLOWED", True)
+REGISTRATION_FORM = get_config("REGISTRATION_FORM", "auth.forms.RegistrationForm")
+
+GRAVATAR_URL = get_config("GRAVATAR_URL", "http://www.gravatar.com/avatar.php?")
+GRAVATAR_SIZE = get_config("GRAVATAR_SIZE", (25, 25))
+GRAVATAR_TYPE = get_config("GRAVATAR_TYPE", "identicon")
+
+ACTIVATION_REQUIRED = get_config("ACTIVATION_REQUIRED", True)
+ACTIVATION_AUTOLOGIN = get_config("ACTIVATION_AUTOLOGIN", True)
+
+ACTIVATION_CONFIRMATION_TYPE = get_config("ACTIVATION_CONFIRMATION_TYPE", 1)
+PASSWORD_RESET_CONFIRMATION_TYPE = get_config("PASSWORD_RESET_CONFIRMATION_TYPE", 2)
+
+LOGIN_REDIRECT_URL = get_config("LOGIN_REDIRECT_URL", "/auth/login/")
+
+USERNAME_REGEX = get_config("USERNAME_REGEX", re.compile(r"[a-z0-9][_a-z0-9]*[a-z0-9]$", re.I))
+USERNAME_MIN_LENGTH = get_config("ACCOUNT_USERNAME_MIN_LENGTH", 3)
+USERNAME_MAX_LENGTH = get_config("ACCOUNT_USERNAME_MAX_LENGTH", 30)
+
+PASSWORD_MIN_LENGTH = get_config("ACCOUNT_PASSWORD_MIN_LENGTH", 1)
+PASSWORD_MAX_LENGTH = get_config("ACCOUNT_PASSWORD_MAX_LENGTH", 30)
+PASSWORD_FIELD_ATTRIBUTES = get_config("PASSWORD_FIELD_ATTRIBUTES", {})
+from setuptools import setup, find_packages
+
+setup(
+    name = "django-auth",
+    version = "0.0.1",
+    packages = find_packages(),
+    author = "Anderson",
+    author_email = "self.anderson@gmail.com",
+    description = "django registration, profile and authentication application.",
+    long_description = """
+        **Download:**
+
+            - hg clone https://offline@bitbucket.org/offline/django-auth/
+
+    """,
+    license = "BSD",
+    keywords = "django",
+    url = "http://bitbucket.org/offline/django-auth/wiki/Home",
+)
+
+def unicode_urlencode(params):
+    """A unicode aware version of urllib.urlencode"""
+    from urllib import urlencode
+
+    if isinstance(params, dict):
+        params = params.items()
+    return urlencode([(k, isinstance(v, unicode) and v.encode('utf-8') or v) for k, v in params])
+
+
+def generate_hash(string=None):
+    import time
+    try:                                                           
+        from hashlib import md5                                    
+    except ImportError:                                            
+        import md5                                                 
+        md5 = md5.new
+
+    if not string:
+        string = str(time.time())
+    hash = md5(string).hexdigest()
+    return hash
+
+
+def build_redirect_url(request, default_url):
+    """
+    Retrieve redirect url from session.
+
+    Use default if retrieved one is broken or not safe.
+    """
+    url = request.session.get('login_redirect_url')
+    if not url or '//' in url or ' ' in url:
+        url = default_url
+    try:
+        del request.session['login_redirect_url']
+    except KeyError:
+        pass
+    return url
+
+
+def parse_template(template_path, **kwargs):
+    """                                     
+    Load and render template.               
+
+    First line of template should contain the subject of email.
+    Return tuple with subject and content.                     
+    """                                                        
+    import re
+
+    from django.template.loader import get_template
+    from django.template import Context
+
+    template = get_template(template_path)
+    context = Context(kwargs)             
+    data = template.render(context).strip()
+    subject, content = re.split(r'\r?\n', data, 1)
+    return (subject.strip(), content.strip())     
+
+
+def email_template(rcpt, template_path, **kwargs):
+    """
+    Load, render and email template.
+
+    **kwargs may contain variables for template rendering.
+    """
+    from django.conf import settings
+    from django.core.mail import send_mail 
+
+    subject, content = parse_template(template_path, **kwargs)
+    count = send_mail(subject, content, settings.DEFAULT_FROM_EMAIL,
+                      [rcpt], fail_silently=True)
+    return bool(count)
+