| Index: appengine_django/auth/__init__.py |
| =================================================================== |
| --- appengine_django/auth/__init__.py (Revision 0) |
| +++ appengine_django/auth/__init__.py (Revision 0) |
| @@ -0,0 +1,206 @@ |
| +# Licensed under the Apache License, Version 2.0 (the "License"); |
|
mattbrown.nz
2008/05/09 10:40:20
You should probably add an Author or Copyright lin
aalbrecht
2008/05/09 20:23:23
On 2008/05/09 10:40:20, mattbrown.nz wrote:
> You
|
| +# you may not use this file except in compliance with the License. |
| +# You may obtain a copy of the License at |
| +# |
| +# http://www.apache.org/licenses/LICENSE-2.0 |
| +# |
| +# Unless required by applicable law or agreed to in writing, software |
| +# distributed under the License is distributed on an "AS IS" BASIS, |
| +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| +# See the License for the specific language governing permissions and |
| +# limitations under the License. |
| + |
| +""" |
| +Authentication module that mimics the behavior of Django's authentication |
| +implementation. |
| + |
| +To use this authentication module in an Appengine/Django project: |
| + - add 'appengine_django.auth.middleware.AuthenticationMiddleware' |
| + to MIDDLEWARE_CLASSES |
| + - add 'appengine_django.auth.context_processors.auth' |
| + to TEMPLATE_CONTEXT_PROCESSORS |
| + |
| +Limitations: |
| + - all user manipulation methods are not available |
| + - all user permissions methods are not available |
| + - user.get_profile method not implemented |
| + - db.UserProperty returns user.User instead of DjangoUser |
| +""" |
| + |
| +from datetime import datetime |
| +import urllib |
| + |
| +from django.db.models.manager import EmptyManager |
| +from django.http import HttpResponseRedirect |
| +from django.template import Node |
| +from django.utils.encoding import smart_str |
| + |
| +from google.appengine.api import datastore_types |
| +from google.appengine.api import mail |
| +from google.appengine.api import users |
| +from google.appengine.ext.webapp import template |
| + |
| +from appengine_django import models |
| + |
| +register = template.create_template_register() |
| +template.register_template_library("appengine_django.auth") |
| + |
|
mattbrown.nz
2008/05/09 10:40:20
add extra blank line
aalbrecht
2008/05/09 20:23:23
On 2008/05/09 10:40:20, mattbrown.nz wrote:
> add
|
| +class CallableString(str): |
| + """String subclass that returns the string if it's called as a function. |
| + This class is required for the user's email attribute.""" |
|
mattbrown.nz
2008/05/09 10:40:20
closing """ on next line.
aalbrecht
2008/05/09 20:23:23
On 2008/05/09 10:40:20, mattbrown.nz wrote:
> clos
|
| + def __call__(self): |
| + return str(self) |
| + |
| + |
| +class DjangoUser(users.User): |
| + """Appengine User subclass that mimics the behavior of an Django user. |
|
mattbrown.nz
2008/05/09 10:40:20
App Engine (nitpick)
aalbrecht
2008/05/09 20:23:23
On 2008/05/09 10:40:20, mattbrown.nz wrote:
> App
|
| + |
| + This class is added to datastore_types when importing this module |
| + to make it usable for db.UserProperty(). |
|
mattbrown.nz
2008/05/09 10:40:20
I don't believe this is possible. See further comm
aalbrecht
2008/05/09 20:23:23
On 2008/05/09 10:40:20, mattbrown.nz wrote:
> I do
|
| + """ |
| + id = None |
| + is_active = True |
| + first_name = None |
| + last_name = None |
| + password = None |
| + _groups = EmptyManager() |
| + _user_permissions = EmptyManager() |
| + |
| + def __init__(self, *args, **kw): |
| + super(DjangoUser, self).__init__(*args, **kw) |
| + self.email = CallableString(self._User__email) |
| + |
| + def __unicode__(self): |
| + return self.username |
| + |
| + def __str__(self): |
| + return unicode(self).encode('utf-8') |
| + |
| + def _get_username(self): |
| + return self.nickname() |
| + username = property(fget=_get_username) |
| + |
| + def _is_superuser(self): |
| + return users.is_current_user_admin() |
| + is_superuser = property(fget=_is_superuser) |
| + is_staff = property(fget=_is_superuser) |
| + |
| + def _default_now(self): |
| + return datetime.now() |
| + last_login = property(fget=_default_now) |
| + date_joined = property(fget=_default_now) |
| + |
| + 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 set_unusable_password(self): |
| + raise NotImplementedError |
| + |
| + def has_usable_password(self): |
| + raise NotImplementedError |
| + |
| + def _get_groups(self): |
| + return self._groups |
| + groups = property(_get_groups) |
| + |
| + def _get_user_permissions(self): |
| + return self._user_permissions |
| + user_permissions = property(_get_user_permissions) |
| + |
| + def get_group_permissions(self): |
| + return self._user_permissions |
| + |
| + def get_all_permissions(self): |
| + return self._user_permissions |
| + |
| + def has_perm(self, perm): |
| + return False |
| + |
| + def has_perms(self, perm_list): |
| + return False |
| + |
| + def has_module_perms(self, module): |
| + return False |
| + |
| + def get_and_delete_messages(self): |
| + return [] |
| + |
| + def is_anonymous(self): |
| + """Always return False""" |
| + return False |
| + |
| + def is_authenticated(self): |
| + """Always return True""" |
| + return True |
| + |
| + def get_absolute_url(self): |
| + return "/users/%s/" % urllib.quote(smart_str(self.username)) |
| + |
| + def get_full_name(self): |
| + return "" |
| + |
| + def email_user(self, subject, message, from_email=None): |
| + """Sends an email to this user""" |
| + mail.send_mail(sender=from_email, |
|
mattbrown.nz
2008/05/09 10:40:20
The App Engine email API requires from_email to be
aalbrecht
2008/05/09 20:23:23
On 2008/05/09 10:40:20, mattbrown.nz wrote:
> The
|
| + to=self.email, |
| + subject=subject, |
| + message=message) |
| + |
| + def get_profile(self): |
| + raise NotImplementedError |
| +datastore_types._PROPERTY_TYPES.append(DjangoUser) |
|
mattbrown.nz
2008/05/09 10:40:20
model properties need to be descended from db.Prop
aalbrecht
2008/05/09 20:23:23
On 2008/05/09 10:40:20, mattbrown.nz wrote:
> mode
mattbrown.nz
2008/05/11 03:01:20
On 2008/05/09 20:23:23, aalbrecht wrote:
> 975, b
aalbrecht
2008/05/13 14:20:24
The DjangoUser class is now a model. I think this
|
| + |
| + |
| +def login_required(function): |
| + """Implementation of Django's login_required decorator. |
| + |
| + The login redirect URL is always set to request.path |
| + """ |
| + def login_required_wrapper(request, *args, **kw): |
| + if request.user.is_authenticated(): |
| + return function(request, *args, **kw) |
| + return HttpResponseRedirect(users.create_login_url(request.path)) |
| + return login_required_wrapper |
| + |
| + |
| +class AuthLoginUrlsNode(Node): |
| + """Template node that creates an appengine login or logout URL. |
| + |
| + If create_login_url is True the appengine's login URL is rendered into |
| + the template, otherwise the logout URL. |
| + """ |
| + def __init__(self, create_login_url, redirect): |
| + self.redirect = redirect |
| + self.create_login_url = create_login_url |
| + |
| + def render(self, context): |
| + if self.create_login_url: |
| + return users.create_login_url(self.redirect) |
| + else: |
| + return users.create_logout_url(self.redirect) |
| + |
|
mattbrown.nz
2008/05/09 10:40:20
add blank line
aalbrecht
2008/05/09 20:23:23
On 2008/05/09 10:40:20, mattbrown.nz wrote:
> add
|
| +def auth_login_urls(parser, token): |
| + """Template tag registered as 'auth_login_url' and 'auth_logout_url' |
| + when the module is imported. |
| + |
| + Both tags take an optional argument that specifies the redirect URL and |
| + defaults to '/'. |
| + """ |
| + bits = list(token.split_contents()) |
| + if len(bits) == 2: |
| + redirect = bits[1] |
| + else: |
| + redirect = "/" |
| + login = bits[0] == "auth_login_url" |
| + return AuthLoginUrlsNode(login, redirect) |
| +register.tag("auth_login_url", auth_login_urls) |
| +register.tag("auth_logout_url", auth_login_urls) |