| LEFT | RIGHT |
|---|---|
| 1 # Copyright 2008 Google Inc. | 1 # Copyright 2008 Google Inc. |
| 2 # | 2 # |
| 3 # Licensed under the Apache License, Version 2.0 (the "License"); | 3 # Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 # you may not use this file except in compliance with the License. | 4 # you may not use this file except in compliance with the License. |
| 5 # You may obtain a copy of the License at | 5 # You may obtain a copy of the License at |
| 6 # | 6 # |
| 7 # http://www.apache.org/licenses/LICENSE-2.0 | 7 # http://www.apache.org/licenses/LICENSE-2.0 |
| 8 # | 8 # |
| 9 # Unless required by applicable law or agreed to in writing, software | 9 # Unless required by applicable law or agreed to in writing, software |
| 10 # distributed under the License is distributed on an "AS IS" BASIS, | 10 # distributed under the License is distributed on an "AS IS" BASIS, |
| 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 # See the License for the specific language governing permissions and | 12 # See the License for the specific language governing permissions and |
| 13 # limitations under the License. | 13 # limitations under the License. |
| 14 | 14 |
| 15 """ | 15 """ |
| 16 DjangoUser model for authentication framework | 16 DjangoUser model for authentication framework |
| 17 """ | 17 """ |
| 18 | 18 |
| 19 from django.contrib.auth.models import SiteProfileNotAvailable | |
| 19 from django.core import mail | 20 from django.core import mail |
| 20 from django.core.exceptions import ImproperlyConfigured | 21 from django.core.exceptions import ImproperlyConfigured |
| 21 from django.db import models | 22 from django.db import models |
| 22 | 23 from django.db.models.manager import EmptyManager |
| 23 try: | |
| 24 # Django >= 0.97 | |
| 25 from django.db.models.manager import EmptyManager | |
| 26 except ImportError: | |
| 27 # Django = 0.96 | |
| 28 from django.db.models.manager import Manager | |
| 29 class EmptyManager(Manager): | |
| 30 def get_query_set(self): | |
| 31 return self.get_empty_query_set() | |
| 32 | 24 |
| 33 from google.appengine.api import users | 25 from google.appengine.api import users |
| 34 from google.appengine.ext import db | 26 from google.appengine.ext import db |
| 35 | 27 |
| 36 from appengine_django.models import BaseModel | 28 from appengine_django.models import BaseModel |
| 37 | 29 |
| 38 | 30 |
| 39 class User(BaseModel): | 31 class DjangoUser(BaseModel): |
| 40 """A model the same attributes and method as a Django user model. | 32 """A model the same attributes and method as a Django user model. |
| 41 | 33 |
| 42 The model has two additions. The first addition is a 'user' attribute | 34 The model has two additions. The first addition is a 'user' attribute |
| 43 which references a App Engine user. The second is the | 35 which references a App Engine user. The second is the |
| 44 'get_djangouser_for_user' classmethod that should be used to retrieve | 36 'get_djangouser_for_user' classmethod that should be used to retrieve |
| 45 a DjangoUser instance from a App Engine user object. | 37 a DjangoUser instance from a App Engine user object. |
| 46 """ | 38 """ |
| 47 user = db.UserProperty(required=True) | 39 user = db.UserProperty(required=True) |
| 48 username = db.StringProperty(required=True) | 40 username = db.StringProperty(required=True) |
| 49 first_name = db.StringProperty() | 41 first_name = db.StringProperty() |
| 50 last_name = db.StringProperty() | 42 last_name = db.StringProperty() |
| 51 email = db.EmailProperty() | 43 email = db.EmailProperty() |
| 52 password = db.StringProperty() | 44 password = db.StringProperty() |
| 53 is_staff = db.BooleanProperty(default=False, required=True) | 45 is_staff = db.BooleanProperty(default=False, required=True) |
| 54 is_active = db.BooleanProperty(default=True, required=True) | 46 is_active = db.BooleanProperty(default=True, required=True) |
| 55 is_superuser = db.BooleanProperty(default=False, required=True) | 47 is_superuser = db.BooleanProperty(default=False, required=True) |
| 56 is_staff = db.BooleanProperty(default=False, required=True) | 48 is_staff = db.BooleanProperty(default=False, required=True) |
| 57 last_login = db.DateTimeProperty(auto_now_add=True, required=True) | 49 last_login = db.DateTimeProperty(auto_now_add=True, required=True) |
| 58 date_joined = db.DateTimeProperty(auto_now_add=True, required=True) | 50 date_joined = db.DateTimeProperty(auto_now_add=True, required=True) |
| 59 groups = EmptyManager() | 51 groups = EmptyManager() |
| 60 user_permissions = EmptyManager() | 52 user_permissions = EmptyManager() |
| 61 | 53 |
| 62 def __unicode__(self): | 54 def __unicode__(self): |
| 63 return self.username | 55 return self.username |
| 64 | 56 |
| 65 def __str__(self): | 57 def __str__(self): |
| 66 return unicode(self).encode('utf-8') | 58 return unicode(self).encode('utf-8') |
| 67 | 59 |
| 68 @classmethod | 60 @classmethod |
| 69 def get_djangouser_for_user(cls, user): | 61 def get_djangouser_for_user(cls, user): |
| 62 email = user.email() | |
| 63 assert email | |
| 64 nickname = user.nickname() | |
| 65 if '@' in nickname: | |
| 66 nickname = nickname.split('@', 1)[0] | |
| 67 assert nickname | |
|
mattbrown.nz
2008/05/18 11:23:43
These statements are only used to create a user, s
aalbrecht
2008/05/18 19:17:47
On 2008/05/18 11:23:43, mattbrown.nz wrote:
> Thes
| |
| 70 query = cls.all().filter("user =", user) | 68 query = cls.all().filter("user =", user) |
| 71 if query.count() == 0: | 69 if query.count() == 0: |
| 72 django_user = cls(user=user, email=user.email(), username=user.nickname()) | 70 django_user = cls(user=user, email=email, username=nickname) |
| 73 django_user.save() | 71 django_user.save() |
| 74 else: | 72 else: |
| 75 django_user = query.get() | 73 django_user = query.get() |
| 76 return django_user | 74 return django_user |
| 77 | 75 |
| 78 def set_password(self, raw_password): | 76 def set_password(self, raw_password): |
| 79 raise NotImplementedError | 77 raise NotImplementedError |
| 80 | 78 |
| 81 def check_password(self, raw_password): | 79 def check_password(self, raw_password): |
| 82 raise NotImplementedError | 80 raise NotImplementedError |
| 83 | 81 |
| 84 def set_unusable_password(self): | 82 def set_unusable_password(self): |
| 85 raise NotImplementedError | 83 raise NotImplementedError |
| 86 | 84 |
| 87 def has_usable_password(self): | 85 def has_usable_password(self): |
| 88 raise NotImplementedError | 86 raise NotImplementedError |
| 89 | 87 |
| 90 def get_group_permissions(self): | 88 def get_group_permissions(self): |
| 91 return self.user_permissions | 89 return self.user_permissions |
| 92 | 90 |
| 93 def get_all_permissions(self): | 91 def get_all_permissions(self): |
| 94 return self.user_permissions | 92 return self.user_permissions |
| 95 | 93 |
| 96 def has_perm(self, perm): | 94 def has_perm(self, perm): |
| 97 return False | 95 return False |
| 98 | 96 |
| 99 def has_perms(self, perm_list): | 97 def has_perms(self, perm_list): |
| 100 return False | 98 return False |
| 101 | 99 |
| 102 def has_module_perms(self, module): | 100 def has_module_perms(self, module): |
| 103 return False | 101 return False |
| 104 | 102 |
| 105 def get_and_delete_messages(self): | 103 def get_and_delete_messages(self): |
| 106 """Gets and deletes messages for this user""" | 104 return [] |
| 107 msgs = [] | |
| 108 for msg in self.message_set: | |
| 109 msgs.append(msg) | |
| 110 msg.delete() | |
| 111 return msgs | |
| 112 | 105 |
| 113 def is_anonymous(self): | 106 def is_anonymous(self): |
| 114 """Always return False""" | 107 """Always return False""" |
| 115 return False | 108 return False |
| 116 | 109 |
| 117 def is_authenticated(self): | 110 def is_authenticated(self): |
| 118 """Always return True""" | 111 """Always return True""" |
| 119 return True | 112 return True |
| 120 | 113 |
| 121 def get_absolute_url(self): | 114 def get_absolute_url(self): |
| 122 return "/users/%s/" % urllib.quote(smart_str(self.username)) | 115 return "/users/%s/" % urllib.quote(smart_str(self.username)) |
| 123 | 116 |
| 124 def get_full_name(self): | 117 def get_full_name(self): |
| 125 full_name = u'%s %s' % (self.first_name, self.last_name) | 118 full_name = u'%s %s' % (self.first_name, self.last_name) |
| 126 return full_name.strip() | 119 return full_name.strip() |
| 127 | 120 |
| 128 def email_user(self, subject, message, from_email): | 121 def email_user(self, subject, message, from_email): |
| 129 """Sends an email to this user. | 122 """Sends an email to this user. |
| 130 | 123 |
| 131 According to the App Engine email API the from_email must be the | 124 According to the App Engine email API the from_email must be the |
| 132 email address of a registered administrator for the application. | 125 email address of a registered administrator for the application. |
| 133 """ | 126 """ |
| 134 mail.send_mail(subject, | 127 mail.send_mail(subject, |
| 135 message, | 128 message, |
| 136 from_email, | 129 from_email, |
| 137 [self.email]) | 130 [self.email]) |
| 138 | 131 |
| 139 def get_profile(self): | 132 def get_profile(self): |
| 140 """ | 133 """ |
| 141 Returns site-specific profile for this user. Raises | 134 Returns site-specific profile for this user. Raises |
| 142 SiteProfileNotAvailable if this site does not allow profiles. | 135 SiteProfileNotAvailable if this site does not allow profiles. |
| 143 | 136 |
| 144 When using the App Engine authentication framework, users are created | 137 When using the App Engine authentication framework, users are created |
| 145 automatically. | 138 automatically. To give projects the chance to create profiles for |
| 139 new users, this method checks for the presence of a classmethod in the | |
| 140 profile model called 'create_profile' if no profile for a user can be found. | |
| 141 If such a method exists, it is called with a DjangoUser as it's only | |
| 142 argument to intially create a profile for this user. The method must return | |
| 143 the created profile. | |
| 146 """ | 144 """ |
| 147 from django.contrib.auth.models import SiteProfileNotAvailable | |
| 148 if not hasattr(self, '_profile_cache'): | 145 if not hasattr(self, '_profile_cache'): |
| 149 from django.conf import settings | 146 from django.conf import settings |
| 150 if not hasattr(settings, "AUTH_PROFILE_MODULE"): | 147 if not hasattr(settings, "AUTH_PROFILE_MODULE"): |
| 151 raise SiteProfileNotAvailable | 148 raise SiteProfileNotAvailable |
| 152 try: | 149 try: |
| 153 app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.') | 150 app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.') |
| 154 model = models.get_model(app_label, model_name) | 151 model = models.get_model(app_label, model_name) |
| 155 self._profile_cache = model.all().filter("user =", self).get() | 152 self._profile_cache = model.all().filter("user =", self).get() |
| 156 if not self._profile_cache: | 153 if not self._profile_cache and hasattr(model, "create_profile"): |
| 157 raise model.DoesNotExist | 154 self._profile_cache = model.create_profile(self) |
|
mattbrown.nz
2008/05/18 11:23:43
else:
raise DoesNotExist
To stay consistent with
aalbrecht
2008/05/18 19:17:47
On 2008/05/18 11:23:43, mattbrown.nz wrote:
> else
| |
| 158 except (ImportError, ImproperlyConfigured): | 155 except (ImportError, ImproperlyConfigured): |
| 159 raise SiteProfileNotAvailable | 156 raise SiteProfileNotAvailable |
| 160 return self._profile_cache | 157 return self._profile_cache |
| 161 | |
| 162 class Group(BaseModel): | |
| 163 """Group model not fully implemented yet.""" | |
| 164 # TODO: Implemented this model, requires contenttypes | |
| 165 name = db.StringProperty() | |
| 166 permissions = EmptyManager() | |
| 167 | |
| 168 class Message(BaseModel): | |
| 169 """User message model""" | |
| 170 user = db.ReferenceProperty(User) | |
| 171 message = db.TextProperty() | |
| 172 | |
| 173 class Permission(BaseModel): | |
| 174 """Permission model not fully implemented yet.""" | |
| 175 # TODO: Implemented this model, requires contenttypes | |
| 176 name = db.StringProperty() | |
| LEFT | RIGHT |