diff options
| author | Adrian Holovaty <adrian@holovaty.com> | 2006-05-02 01:31:56 +0000 |
|---|---|---|
| committer | Adrian Holovaty <adrian@holovaty.com> | 2006-05-02 01:31:56 +0000 |
| commit | f69cf70ed813a8cd7e1f963a14ae39103e8d5265 (patch) | |
| tree | d3b32e84cd66573b3833ddf662af020f8ef2f7a8 /django/contrib/auth | |
| parent | d5dbeaa9be359a4c794885c2e9f1b5a7e5e51fb8 (diff) | |
MERGED MAGIC-REMOVAL BRANCH TO TRUNK. This change is highly backwards-incompatible. Please read http://code.djangoproject.com/wiki/RemovingTheMagic for upgrade instructions.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@2809 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/contrib/auth')
| -rw-r--r-- | django/contrib/auth/__init__.py | 2 | ||||
| -rw-r--r-- | django/contrib/auth/create_superuser.py | 84 | ||||
| -rw-r--r-- | django/contrib/auth/decorators.py | 25 | ||||
| -rw-r--r-- | django/contrib/auth/forms.py | 108 | ||||
| -rw-r--r-- | django/contrib/auth/handlers/modpython.py | 12 | ||||
| -rw-r--r-- | django/contrib/auth/management.py | 53 | ||||
| -rw-r--r-- | django/contrib/auth/middleware.py | 19 | ||||
| -rw-r--r-- | django/contrib/auth/models.py | 264 | ||||
| -rw-r--r-- | django/contrib/auth/views.py | 84 |
9 files changed, 645 insertions, 6 deletions
diff --git a/django/contrib/auth/__init__.py b/django/contrib/auth/__init__.py index e69de29bb2..ac7b40aca6 100644 --- a/django/contrib/auth/__init__.py +++ b/django/contrib/auth/__init__.py @@ -0,0 +1,2 @@ +LOGIN_URL = '/accounts/login/' +REDIRECT_FIELD_NAME = 'next' diff --git a/django/contrib/auth/create_superuser.py b/django/contrib/auth/create_superuser.py new file mode 100644 index 0000000000..ab5ca36f50 --- /dev/null +++ b/django/contrib/auth/create_superuser.py @@ -0,0 +1,84 @@ +""" +Helper function for creating superusers in the authentication system. +""" + +from django.core import validators +from django.contrib.auth.models import User +import getpass +import os +import sys + +def createsuperuser(username=None, email=None, password=None): + """ + Helper function for creating a superuser from the command line. All + arguments are optional and will be prompted-for if invalid or not given. + """ + try: + import pwd + except ImportError: + default_username = '' + else: + # Determine the current system user's username, to use as a default. + default_username = pwd.getpwuid(os.getuid())[0].replace(' ', '').lower() + + # Determine whether the default username is taken, so we don't display + # it as an option. + if default_username: + try: + User.objects.get(username=default_username) + except User.DoesNotExist: + pass + else: + default_username = '' + + try: + while 1: + if not username: + input_msg = 'Username' + if default_username: + input_msg += ' (Leave blank to use %r)' % default_username + username = raw_input(input_msg + ': ') + if default_username and username == '': + username = default_username + if not username.isalnum(): + sys.stderr.write("Error: That username is invalid. Use only letters, digits and underscores.\n") + username = None + try: + User.objects.get(username=username) + except User.DoesNotExist: + break + else: + sys.stderr.write("Error: That username is already taken.\n") + username = None + while 1: + if not email: + email = raw_input('E-mail address: ') + try: + validators.isValidEmail(email, None) + except validators.ValidationError: + sys.stderr.write("Error: That e-mail address is invalid.\n") + email = None + else: + break + while 1: + if not password: + password = getpass.getpass() + password2 = getpass.getpass('Password (again): ') + if password != password2: + sys.stderr.write("Error: Your passwords didn't match.\n") + password = None + continue + if password.strip() == '': + sys.stderr.write("Error: Blank passwords aren't allowed.\n") + password = None + continue + break + except KeyboardInterrupt: + sys.stderr.write("\nOperation cancelled.\n") + sys.exit(1) + u = User.objects.create_user(username, email, password) + u.is_staff = True + u.is_active = True + u.is_superuser = True + u.save() + print "Superuser created successfully." diff --git a/django/contrib/auth/decorators.py b/django/contrib/auth/decorators.py new file mode 100644 index 0000000000..4b264cf815 --- /dev/null +++ b/django/contrib/auth/decorators.py @@ -0,0 +1,25 @@ +from django.contrib.auth import LOGIN_URL, REDIRECT_FIELD_NAME +from django.http import HttpResponseRedirect + +def user_passes_test(test_func, login_url=LOGIN_URL): + """ + Decorator for views that checks that the user passes the given test, + redirecting to the log-in page if necessary. The test should be a callable + that takes the user object and returns True if the user passes. + """ + def _dec(view_func): + def _checklogin(request, *args, **kwargs): + if test_func(request.user): + return view_func(request, *args, **kwargs) + return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, request.path)) + + return _checklogin + return _dec + +login_required = user_passes_test(lambda u: not u.is_anonymous()) +login_required.__doc__ = ( + """ + Decorator for views that checks that the user is logged in, redirecting + to the log-in page if necessary. + """ + ) diff --git a/django/contrib/auth/forms.py b/django/contrib/auth/forms.py new file mode 100644 index 0000000000..6c0c8abe97 --- /dev/null +++ b/django/contrib/auth/forms.py @@ -0,0 +1,108 @@ +from django.contrib.auth.models import User +from django.contrib.sites.models import Site +from django.template import Context, loader +from django.core import validators +from django import forms + +class AuthenticationForm(forms.Manipulator): + """ + Base class for authenticating users. Extend this to get a form that accepts + username/password logins. + """ + def __init__(self, request=None): + """ + If request is passed in, the manipulator will validate that cookies are + enabled. Note that the request (a HttpRequest object) must have set a + cookie with the key TEST_COOKIE_NAME and value TEST_COOKIE_VALUE before + running this validator. + """ + self.request = request + self.fields = [ + forms.TextField(field_name="username", length=15, maxlength=30, is_required=True, + validator_list=[self.isValidUser, self.hasCookiesEnabled]), + forms.PasswordField(field_name="password", length=15, maxlength=30, is_required=True, + validator_list=[self.isValidPasswordForUser]), + ] + self.user_cache = None + + def hasCookiesEnabled(self, field_data, all_data): + if self.request and not self.request.session.test_cookie_worked(): + raise validators.ValidationError, _("Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in.") + + def isValidUser(self, field_data, all_data): + try: + self.user_cache = User.objects.get(username=field_data) + except User.DoesNotExist: + raise validators.ValidationError, _("Please enter a correct username and password. Note that both fields are case-sensitive.") + + def isValidPasswordForUser(self, field_data, all_data): + if self.user_cache is not None and not self.user_cache.check_password(field_data): + self.user_cache = None + raise validators.ValidationError, _("Please enter a correct username and password. Note that both fields are case-sensitive.") + + def get_user_id(self): + if self.user_cache: + return self.user_cache.id + return None + + def get_user(self): + return self.user_cache + +class PasswordResetForm(forms.Manipulator): + "A form that lets a user request a password reset" + def __init__(self): + self.fields = ( + forms.EmailField(field_name="email", length=40, is_required=True, + validator_list=[self.isValidUserEmail]), + ) + + def isValidUserEmail(self, new_data, all_data): + "Validates that a user exists with the given e-mail address" + try: + self.user_cache = User.objects.get(email__iexact=new_data) + except User.DoesNotExist: + raise validators.ValidationError, "That e-mail address doesn't have an associated user acount. Are you sure you've registered?" + + def save(self, domain_override=None): + "Calculates a new password randomly and sends it to the user" + from django.core.mail import send_mail + new_pass = User.objects.make_random_password() + self.user_cache.set_password(new_pass) + self.user_cache.save() + if not domain_override: + current_site = Site.objects.get_current() + site_name = current_site.name + domain = current_site.domain + else: + site_name = domain = domain_override + t = loader.get_template('registration/password_reset_email.html') + c = { + 'new_password': new_pass, + 'email': self.user_cache.email, + 'domain': domain, + 'site_name': site_name, + 'user': self.user_cache, + } + send_mail('Password reset on %s' % site_name, t.render(Context(c)), None, [self.user_cache.email]) + +class PasswordChangeForm(forms.Manipulator): + "A form that lets a user change his password." + def __init__(self, user): + self.user = user + self.fields = ( + forms.PasswordField(field_name="old_password", length=30, maxlength=30, is_required=True, + validator_list=[self.isValidOldPassword]), + forms.PasswordField(field_name="new_password1", length=30, maxlength=30, is_required=True, + validator_list=[validators.AlwaysMatchesOtherField('new_password2', "The two 'new password' fields didn't match.")]), + forms.PasswordField(field_name="new_password2", length=30, maxlength=30, is_required=True), + ) + + def isValidOldPassword(self, new_data, all_data): + "Validates that the old_password field is correct." + if not self.user.check_password(new_data): + raise validators.ValidationError, "Your old password was entered incorrectly. Please enter it again." + + def save(self, new_data): + "Saves the new password." + self.user.set_password(new_data['new_password1']) + self.user.save() diff --git a/django/contrib/auth/handlers/modpython.py b/django/contrib/auth/handlers/modpython.py index d538c9ccc8..b1d7680a33 100644 --- a/django/contrib/auth/handlers/modpython.py +++ b/django/contrib/auth/handlers/modpython.py @@ -10,7 +10,7 @@ def authenhandler(req, **kwargs): # that so that the following import works os.environ.update(req.subprocess_env) - from django.models.auth import users + from django.contrib.auth.models import User # check for PythonOptions _str_to_bool = lambda s: s.lower() in ('1', 'true', 'on', 'yes') @@ -21,14 +21,14 @@ def authenhandler(req, **kwargs): superuser_only = _str_to_bool(options.get('DjangoRequireSuperuserStatus', "off")) # check that the username is valid - kwargs = {'username__exact': req.user, 'is_active__exact': True} + kwargs = {'username': req.user, 'is_active': True} if staff_only: - kwargs['is_staff__exact'] = True + kwargs['is_staff'] = True if superuser_only: - kwargs['is_superuser__exact'] = True + kwargs['is_superuser'] = True try: - user = users.get_object(**kwargs) - except users.UserDoesNotExist: + user = User.objects.get(**kwargs) + except User.DoesNotExist: return apache.HTTP_UNAUTHORIZED # check the password and any permission given diff --git a/django/contrib/auth/management.py b/django/contrib/auth/management.py new file mode 100644 index 0000000000..fe3399edbb --- /dev/null +++ b/django/contrib/auth/management.py @@ -0,0 +1,53 @@ +""" +Creates permissions for all installed apps that need permissions. +""" + +from django.dispatch import dispatcher +from django.db.models import get_models, signals +from django.contrib.auth import models as auth_app + +def _get_permission_codename(action, opts): + return '%s_%s' % (action, opts.object_name.lower()) + +def _get_all_permissions(opts): + "Returns (codename, name) for all permissions in the given opts." + perms = [] + for action in ('add', 'change', 'delete'): + perms.append((_get_permission_codename(action, opts), 'Can %s %s' % (action, opts.verbose_name))) + return perms + list(opts.permissions) + +def create_permissions(app, created_models): + from django.contrib.contenttypes.models import ContentType + from django.contrib.auth.models import Permission + app_models = get_models(app) + if not app_models: + return + for klass in app_models: + if not klass._meta.admin: + continue + ctype = ContentType.objects.get_for_model(klass) + for codename, name in _get_all_permissions(klass._meta): + try: + Permission.objects.get(name=name, codename=codename, content_type__pk=ctype.id) + except Permission.DoesNotExist: + p = Permission(name=name, codename=codename, content_type=ctype) + p.save() + print "Adding permission '%s'" % p + +def create_superuser(app, created_models): + from django.contrib.auth.models import User + from django.contrib.auth.create_superuser import createsuperuser as do_create + if User in created_models: + msg = "\nYou just installed Django's auth system, which means you don't have " \ + "any superusers defined.\nWould you like to create one now? (yes/no): " + confirm = raw_input(msg) + while 1: + if confirm not in ('yes', 'no'): + confirm = raw_input('Please enter either "yes" or "no": ') + continue + if confirm == 'yes': + do_create() + break + +dispatcher.connect(create_permissions, signal=signals.post_syncdb) +dispatcher.connect(create_superuser, sender=auth_app, signal=signals.post_syncdb) diff --git a/django/contrib/auth/middleware.py b/django/contrib/auth/middleware.py new file mode 100644 index 0000000000..4b3ed54960 --- /dev/null +++ b/django/contrib/auth/middleware.py @@ -0,0 +1,19 @@ +class LazyUser(object): + def __init__(self): + self._user = None + + def __get__(self, request, obj_type=None): + if self._user is None: + from django.contrib.auth.models import User, AnonymousUser, SESSION_KEY + try: + user_id = request.session[SESSION_KEY] + self._user = User.objects.get(pk=user_id) + except (KeyError, User.DoesNotExist): + self._user = AnonymousUser() + return self._user + +class AuthenticationMiddleware: + def process_request(self, request): + assert hasattr(request, 'session'), "The Django authentication middleware requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'." + request.__class__.user = LazyUser() + return None diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py new file mode 100644 index 0000000000..cea7a694c9 --- /dev/null +++ b/django/contrib/auth/models.py @@ -0,0 +1,264 @@ +from django.core import validators +from django.db import backend, connection, models +from django.contrib.contenttypes.models import ContentType +from django.utils.translation import gettext_lazy as _ +import datetime + +SESSION_KEY = '_auth_user_id' + +class SiteProfileNotAvailable(Exception): + pass + +class Permission(models.Model): + name = models.CharField(_('name'), maxlength=50) + content_type = models.ForeignKey(ContentType) + codename = models.CharField(_('codename'), maxlength=100) + class Meta: + verbose_name = _('permission') + verbose_name_plural = _('permissions') + unique_together = (('content_type', 'codename'),) + ordering = ('content_type', 'codename') + + def __str__(self): + return "%r | %s" % (self.content_type, self.name) + +class Group(models.Model): + name = models.CharField(_('name'), maxlength=80, unique=True) + permissions = models.ManyToManyField(Permission, verbose_name=_('permissions'), blank=True, filter_interface=models.HORIZONTAL) + class Meta: + verbose_name = _('group') + verbose_name_plural = _('groups') + ordering = ('name',) + class Admin: + search_fields = ('name',) + + def __str__(self): + return self.name + +class UserManager(models.Manager): + def create_user(self, username, email, password): + "Creates and saves a User with the given username, e-mail and password." + now = datetime.datetime.now() + user = self.model(None, username, '', '', email.strip().lower(), 'placeholder', False, True, False, now, now) + user.set_password(password) + user.save() + return user + + def make_random_password(self, length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789'): + "Generates a random password with the given length and given allowed_chars" + # Note that default value of allowed_chars does not have "I" or letters + # that look like it -- just to avoid confusion. + from random import choice + return ''.join([choice(allowed_chars) for i in range(length)]) + +class User(models.Model): + username = models.CharField(_('username'), maxlength=30, unique=True, validator_list=[validators.isAlphaNumeric]) + first_name = models.CharField(_('first name'), maxlength=30, blank=True) + last_name = models.CharField(_('last name'), maxlength=30, blank=True) + email = models.EmailField(_('e-mail address'), blank=True) + password = models.CharField(_('password'), maxlength=128, help_text=_("Use '[algo]$[salt]$[hexdigest]'")) + is_staff = models.BooleanField(_('staff status'), help_text=_("Designates whether the user can log into this admin site.")) + is_active = models.BooleanField(_('active'), default=True) + is_superuser = models.BooleanField(_('superuser status')) + last_login = models.DateTimeField(_('last login'), default=models.LazyDate()) + date_joined = models.DateTimeField(_('date joined'), default=models.LazyDate()) + groups = models.ManyToManyField(Group, verbose_name=_('groups'), blank=True, + help_text=_("In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in.")) + user_permissions = models.ManyToManyField(Permission, verbose_name=_('user permissions'), blank=True, filter_interface=models.HORIZONTAL) + objects = UserManager() + class Meta: + verbose_name = _('user') + verbose_name_plural = _('users') + ordering = ('username',) + class Admin: + fields = ( + (None, {'fields': ('username', 'password')}), + (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}), + (_('Permissions'), {'fields': ('is_staff', 'is_active', 'is_superuser', 'user_permissions')}), + (_('Important dates'), {'fields': ('last_login', 'date_joined')}), + (_('Groups'), {'fields': ('groups',)}), + ) + list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff') + list_filter = ('is_staff', 'is_superuser') + search_fields = ('username', 'first_name', 'last_name', 'email') + + def __str__(self): + return self.username + + def get_absolute_url(self): + return "/users/%s/" % self.username + + def is_anonymous(self): + return False + + def get_full_name(self): + full_name = '%s %s' % (self.first_name, self.last_name) + return full_name.strip() + + def set_password(self, raw_password): + import sha, random + algo = 'sha1' + salt = sha.new(str(random.random())).hexdigest()[:5] + hsh = sha.new(salt+raw_password).hexdigest() + self.password = '%s$%s$%s' % (algo, salt, hsh) + + def check_password(self, raw_password): + """ + Returns a boolean of whether the raw_password was correct. Handles + encryption formats behind the scenes. + """ + # Backwards-compatibility check. Older passwords won't include the + # algorithm or salt. + if '$' not in self.password: + import md5 + is_correct = (self.password == md5.new(raw_password).hexdigest()) + if is_correct: + # Convert the password to the new, more secure format. + self.set_password(raw_password) + self.save() + return is_correct + algo, salt, hsh = self.password.split('$') + if algo == 'md5': + import md5 + return hsh == md5.new(salt+raw_password).hexdigest() + elif algo == 'sha1': + import sha + return hsh == sha.new(salt+raw_password).hexdigest() + raise ValueError, "Got unknown password algorithm type in password." + + def get_group_permissions(self): + "Returns a list of permission strings that this user has through his/her groups." + if not hasattr(self, '_group_perm_cache'): + import sets + cursor = connection.cursor() + # The SQL below works out to the following, after DB quoting: + # cursor.execute(""" + # SELECT ct."app_label", p."codename" + # FROM "auth_permission" p, "auth_group_permissions" gp, "auth_user_groups" ug, "django_content_type" ct + # WHERE p."id" = gp."permission_id" + # AND gp."group_id" = ug."group_id" + # AND ct."id" = p."content_type_id" + # AND ug."user_id" = %s, [self.id]) + sql = """ + SELECT ct.%s, p.%s + FROM %s p, %s gp, %s ug, %s ct + WHERE p.%s = gp.%s + AND gp.%s = ug.%s + AND ct.%s = p.%s + AND ug.%s = %%s""" % ( + backend.quote_name('app_label'), backend.quote_name('codename'), + backend.quote_name('auth_permission'), backend.quote_name('auth_group_permissions'), + backend.quote_name('auth_user_groups'), backend.quote_name('django_content_type'), + backend.quote_name('id'), backend.quote_name('permission_id'), + backend.quote_name('group_id'), backend.quote_name('group_id'), + backend.quote_name('id'), backend.quote_name('content_type_id'), + backend.quote_name('user_id'),) + cursor.execute(sql, [self.id]) + self._group_perm_cache = sets.Set(["%s.%s" % (row[0], row[1]) for row in cursor.fetchall()]) + return self._group_perm_cache + + def get_all_permissions(self): + if not hasattr(self, '_perm_cache'): + import sets + self._perm_cache = sets.Set(["%s.%s" % (p.content_type.app_label, p.codename) for p in self.user_permissions.all()]) + self._perm_cache.update(self.get_group_permissions()) + return self._perm_cache + + def has_perm(self, perm): + "Returns True if the user has the specified permission." + if not self.is_active: + return False + if self.is_superuser: + return True + return perm in self.get_all_permissions() + + def has_perms(self, perm_list): + "Returns True if the user has each of the specified permissions." + for perm in perm_list: + if not self.has_perm(perm): + return False + return True + + def has_module_perms(self, app_label): + "Returns True if the user has any permissions in the given app label." + if self.is_superuser: + return True + return bool(len([p for p in self.get_all_permissions() if p[:p.index('.')] == app_label])) + + def get_and_delete_messages(self): + messages = [] + for m in self.message_set.all(): + messages.append(m.message) + m.delete() + return messages + + def email_user(self, subject, message, from_email=None): + "Sends an e-mail to this User." + from django.core.mail import send_mail + send_mail(subject, message, from_email, [self.email]) + + def get_profile(self): + """ + Returns site-specific profile for this user. Raises + SiteProfileNotAvailable if this site does not allow profiles. + """ + if not hasattr(self, '_profile_cache'): + from django.conf import settings + if not settings.AUTH_PROFILE_MODULE: + raise SiteProfileNotAvailable + try: + app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.') + model = models.get_model(app_label, model_name) + self._profile_cache = model._default_manager.get(user__id__exact=self.id) + except ImportError, ImproperlyConfigured: + raise SiteProfileNotAvailable + return self._profile_cache + +class Message(models.Model): + user = models.ForeignKey(User) + message = models.TextField(_('message')) + + def __str__(self): + return self.message + +class AnonymousUser(object): + id = None + username = '' + + def __init__(self): + pass + + def __str__(self): + return 'AnonymousUser' + + def save(self): + raise NotImplementedError + + def delete(self): + raise NotImplementedError + + def set_password(self, raw_password): + raise NotImplementedError + + def check_password(self, raw_password): + raise NotImplementedError + + def _get_groups(self): + raise NotImplementedError + groups = property(_get_groups) + + def _get_user_permissions(self): + raise NotImplementedError + user_permissions = property(_get_user_permissions) + + def has_perm(self, perm): + return False + + def has_module_perms(self, module): + return False + + def get_and_delete_messages(self): + return [] + + def is_anonymous(self): + return True diff --git a/django/contrib/auth/views.py b/django/contrib/auth/views.py new file mode 100644 index 0000000000..f919f82419 --- /dev/null +++ b/django/contrib/auth/views.py @@ -0,0 +1,84 @@ +from django.contrib.auth.forms import AuthenticationForm +from django.contrib.auth.forms import PasswordResetForm, PasswordChangeForm +from django import forms +from django.shortcuts import render_to_response +from django.template import RequestContext +from django.contrib.auth.models import SESSION_KEY +from django.contrib.sites.models import Site +from django.http import HttpResponse, HttpResponseRedirect +from django.contrib.auth.decorators import login_required +from django.contrib.auth import LOGIN_URL, REDIRECT_FIELD_NAME + +def login(request): + "Displays the login form and handles the login action." + manipulator = AuthenticationForm(request) + redirect_to = request.REQUEST.get(REDIRECT_FIELD_NAME, '') + if request.POST: + errors = manipulator.get_validation_errors(request.POST) + if not errors: + # Light security check -- make sure redirect_to isn't garbage. + if not redirect_to or '://' in redirect_to or ' ' in redirect_to: + redirect_to = '/accounts/profile/' + request.session[SESSION_KEY] = manipulator.get_user_id() + request.session.delete_test_cookie() + return HttpResponseRedirect(redirect_to) + else: + errors = {} + request.session.set_test_cookie() + return render_to_response('registration/login.html', { + 'form': forms.FormWrapper(manipulator, request.POST, errors), + REDIRECT_FIELD_NAME: redirect_to, + 'site_name': Site.objects.get_current().name, + }, context_instance=RequestContext(request)) + +def logout(request, next_page=None): + "Logs out the user and displays 'You are logged out' message." + try: + del request.session[SESSION_KEY] + except KeyError: + return render_to_response('registration/logged_out.html', {'title': 'Logged out'}, context_instance=RequestContext(request)) + else: + # Redirect to this page until the session has been cleared. + return HttpResponseRedirect(next_page or request.path) + +def logout_then_login(request, login_url=LOGIN_URL): + "Logs out the user if he is logged in. Then redirects to the log-in page." + return logout(request, login_url) + +def redirect_to_login(next, login_url=LOGIN_URL): + "Redirects the user to the login page, passing the given 'next' page" + return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, next)) + +def password_reset(request, is_admin_site=False): + new_data, errors = {}, {} + form = PasswordResetForm() + if request.POST: + new_data = request.POST.copy() + errors = form.get_validation_errors(new_data) + if not errors: + if is_admin_site: + form.save(request.META['HTTP_HOST']) + else: + form.save() + return HttpResponseRedirect('%sdone/' % request.path) + return render_to_response('registration/password_reset_form.html', {'form': forms.FormWrapper(form, new_data, errors)}, + context_instance=RequestContext(request)) + +def password_reset_done(request): + return render_to_response('registration/password_reset_done.html', context_instance=RequestContext(request)) + +def password_change(request): + new_data, errors = {}, {} + form = PasswordChangeForm(request.user) + if request.POST: + new_data = request.POST.copy() + errors = form.get_validation_errors(new_data) + if not errors: + form.save(new_data) + return HttpResponseRedirect('%sdone/' % request.path) + return render_to_response('registration/password_change_form.html', {'form': forms.FormWrapper(form, new_data, errors)}, + context_instance=RequestContext(request)) +password_change = login_required(password_change) + +def password_change_done(request): + return render_to_response('registration/password_change_done.html', context_instance=RequestContext(request)) |
