|
1 import datetime |
|
2 import urllib |
|
3 |
1 from django.contrib import auth |
4 from django.contrib import auth |
2 from django.core import validators |
|
3 from django.core.exceptions import ImproperlyConfigured |
5 from django.core.exceptions import ImproperlyConfigured |
4 from django.db import models |
6 from django.db import models |
5 from django.db.models.manager import EmptyManager |
7 from django.db.models.manager import EmptyManager |
6 from django.contrib.contenttypes.models import ContentType |
8 from django.contrib.contenttypes.models import ContentType |
7 from django.utils.encoding import smart_str |
9 from django.utils.encoding import smart_str |
|
10 from django.utils.hashcompat import md5_constructor, sha_constructor |
8 from django.utils.translation import ugettext_lazy as _ |
11 from django.utils.translation import ugettext_lazy as _ |
9 import datetime |
|
10 import urllib |
|
11 |
12 |
12 UNUSABLE_PASSWORD = '!' # This will never be a valid hash |
13 UNUSABLE_PASSWORD = '!' # This will never be a valid hash |
13 |
14 |
14 try: |
15 try: |
15 set |
16 set |
26 try: |
27 try: |
27 import crypt |
28 import crypt |
28 except ImportError: |
29 except ImportError: |
29 raise ValueError('"crypt" password algorithm not supported in this environment') |
30 raise ValueError('"crypt" password algorithm not supported in this environment') |
30 return crypt.crypt(raw_password, salt) |
31 return crypt.crypt(raw_password, salt) |
31 # The rest of the supported algorithms are supported by hashlib, but |
32 |
32 # hashlib is only available in Python 2.5. |
33 if algorithm == 'md5': |
33 try: |
34 return md5_constructor(salt + raw_password).hexdigest() |
34 import hashlib |
35 elif algorithm == 'sha1': |
35 except ImportError: |
36 return sha_constructor(salt + raw_password).hexdigest() |
36 if algorithm == 'md5': |
|
37 import md5 |
|
38 return md5.new(salt + raw_password).hexdigest() |
|
39 elif algorithm == 'sha1': |
|
40 import sha |
|
41 return sha.new(salt + raw_password).hexdigest() |
|
42 else: |
|
43 if algorithm == 'md5': |
|
44 return hashlib.md5(salt + raw_password).hexdigest() |
|
45 elif algorithm == 'sha1': |
|
46 return hashlib.sha1(salt + raw_password).hexdigest() |
|
47 raise ValueError("Got unknown password algorithm type in password.") |
37 raise ValueError("Got unknown password algorithm type in password.") |
48 |
38 |
49 def check_password(raw_password, enc_password): |
39 def check_password(raw_password, enc_password): |
50 """ |
40 """ |
51 Returns a boolean of whether the raw_password was correct. Handles |
41 Returns a boolean of whether the raw_password was correct. Handles |
76 |
66 |
77 class Meta: |
67 class Meta: |
78 verbose_name = _('permission') |
68 verbose_name = _('permission') |
79 verbose_name_plural = _('permissions') |
69 verbose_name_plural = _('permissions') |
80 unique_together = (('content_type', 'codename'),) |
70 unique_together = (('content_type', 'codename'),) |
81 ordering = ('content_type', 'codename') |
71 ordering = ('content_type__app_label', 'codename') |
82 |
72 |
83 def __unicode__(self): |
73 def __unicode__(self): |
84 return u"%s | %s | %s" % (self.content_type.app_label, self.content_type, self.name) |
74 return u"%s | %s | %s" % ( |
|
75 unicode(self.content_type.app_label), |
|
76 unicode(self.content_type), |
|
77 unicode(self.name)) |
85 |
78 |
86 class Group(models.Model): |
79 class Group(models.Model): |
87 """Groups are a generic way of categorizing users to apply permissions, or some other label, to those users. A user can belong to any number of groups. |
80 """Groups are a generic way of categorizing users to apply permissions, or some other label, to those users. A user can belong to any number of groups. |
88 |
81 |
89 A user in a group automatically has all the permissions granted to that group. For example, if the group Site editors has the permission can_edit_home_page, any user in that group will have that permission. |
82 A user in a group automatically has all the permissions granted to that group. For example, if the group Site editors has the permission can_edit_home_page, any user in that group will have that permission. |
90 |
83 |
91 Beyond permissions, groups are a convenient way to categorize users to apply some label, or extended functionality, to them. For example, you could create a group 'Special users', and you could write code that would do special things to those users -- such as giving them access to a members-only portion of your site, or sending them members-only e-mail messages. |
84 Beyond permissions, groups are a convenient way to categorize users to apply some label, or extended functionality, to them. For example, you could create a group 'Special users', and you could write code that would do special things to those users -- such as giving them access to a members-only portion of your site, or sending them members-only e-mail messages. |
92 """ |
85 """ |
93 name = models.CharField(_('name'), max_length=80, unique=True) |
86 name = models.CharField(_('name'), max_length=80, unique=True) |
94 permissions = models.ManyToManyField(Permission, verbose_name=_('permissions'), blank=True, filter_interface=models.HORIZONTAL) |
87 permissions = models.ManyToManyField(Permission, verbose_name=_('permissions'), blank=True) |
95 |
88 |
96 class Meta: |
89 class Meta: |
97 verbose_name = _('group') |
90 verbose_name = _('group') |
98 verbose_name_plural = _('groups') |
91 verbose_name_plural = _('groups') |
99 ordering = ('name',) |
|
100 |
|
101 class Admin: |
|
102 search_fields = ('name',) |
|
103 |
92 |
104 def __unicode__(self): |
93 def __unicode__(self): |
105 return self.name |
94 return self.name |
106 |
95 |
107 class UserManager(models.Manager): |
96 class UserManager(models.Manager): |
114 else: |
103 else: |
115 user.set_unusable_password() |
104 user.set_unusable_password() |
116 user.save() |
105 user.save() |
117 return user |
106 return user |
118 |
107 |
|
108 def create_superuser(self, username, email, password): |
|
109 u = self.create_user(username, email, password) |
|
110 u.is_staff = True |
|
111 u.is_active = True |
|
112 u.is_superuser = True |
|
113 u.save() |
|
114 |
119 def make_random_password(self, length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789'): |
115 def make_random_password(self, length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789'): |
120 "Generates a random password with the given length and given allowed_chars" |
116 "Generates a random password with the given length and given allowed_chars" |
121 # Note that default value of allowed_chars does not have "I" or letters |
117 # Note that default value of allowed_chars does not have "I" or letters |
122 # that look like it -- just to avoid confusion. |
118 # that look like it -- just to avoid confusion. |
123 from random import choice |
119 from random import choice |
126 class User(models.Model): |
122 class User(models.Model): |
127 """Users within the Django authentication system are represented by this model. |
123 """Users within the Django authentication system are represented by this model. |
128 |
124 |
129 Username and password are required. Other fields are optional. |
125 Username and password are required. Other fields are optional. |
130 """ |
126 """ |
131 username = models.CharField(_('username'), max_length=30, unique=True, validator_list=[validators.isAlphaNumeric], help_text=_("Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores).")) |
127 username = models.CharField(_('username'), max_length=30, unique=True, help_text=_("Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores).")) |
132 first_name = models.CharField(_('first name'), max_length=30, blank=True) |
128 first_name = models.CharField(_('first name'), max_length=30, blank=True) |
133 last_name = models.CharField(_('last name'), max_length=30, blank=True) |
129 last_name = models.CharField(_('last name'), max_length=30, blank=True) |
134 email = models.EmailField(_('e-mail address'), blank=True) |
130 email = models.EmailField(_('e-mail address'), blank=True) |
135 password = models.CharField(_('password'), max_length=128, help_text=_("Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change password form</a>.")) |
131 password = models.CharField(_('password'), max_length=128, help_text=_("Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change password form</a>.")) |
136 is_staff = models.BooleanField(_('staff status'), default=False, help_text=_("Designates whether the user can log into this admin site.")) |
132 is_staff = models.BooleanField(_('staff status'), default=False, help_text=_("Designates whether the user can log into this admin site.")) |
138 is_superuser = models.BooleanField(_('superuser status'), default=False, help_text=_("Designates that this user has all permissions without explicitly assigning them.")) |
134 is_superuser = models.BooleanField(_('superuser status'), default=False, help_text=_("Designates that this user has all permissions without explicitly assigning them.")) |
139 last_login = models.DateTimeField(_('last login'), default=datetime.datetime.now) |
135 last_login = models.DateTimeField(_('last login'), default=datetime.datetime.now) |
140 date_joined = models.DateTimeField(_('date joined'), default=datetime.datetime.now) |
136 date_joined = models.DateTimeField(_('date joined'), default=datetime.datetime.now) |
141 groups = models.ManyToManyField(Group, verbose_name=_('groups'), blank=True, |
137 groups = models.ManyToManyField(Group, verbose_name=_('groups'), blank=True, |
142 help_text=_("In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in.")) |
138 help_text=_("In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in.")) |
143 user_permissions = models.ManyToManyField(Permission, verbose_name=_('user permissions'), blank=True, filter_interface=models.HORIZONTAL) |
139 user_permissions = models.ManyToManyField(Permission, verbose_name=_('user permissions'), blank=True) |
144 objects = UserManager() |
140 objects = UserManager() |
145 |
141 |
146 class Meta: |
142 class Meta: |
147 verbose_name = _('user') |
143 verbose_name = _('user') |
148 verbose_name_plural = _('users') |
144 verbose_name_plural = _('users') |
149 ordering = ('username',) |
|
150 |
|
151 class Admin: |
|
152 fields = ( |
|
153 (None, {'fields': ('username', 'password')}), |
|
154 (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}), |
|
155 (_('Permissions'), {'fields': ('is_staff', 'is_active', 'is_superuser', 'user_permissions')}), |
|
156 (_('Important dates'), {'fields': ('last_login', 'date_joined')}), |
|
157 (_('Groups'), {'fields': ('groups',)}), |
|
158 ) |
|
159 list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff') |
|
160 list_filter = ('is_staff', 'is_superuser') |
|
161 search_fields = ('username', 'first_name', 'last_name', 'email') |
|
162 |
145 |
163 def __unicode__(self): |
146 def __unicode__(self): |
164 return self.username |
147 return self.username |
165 |
148 |
166 def get_absolute_url(self): |
149 def get_absolute_url(self): |
291 Returns site-specific profile for this user. Raises |
274 Returns site-specific profile for this user. Raises |
292 SiteProfileNotAvailable if this site does not allow profiles. |
275 SiteProfileNotAvailable if this site does not allow profiles. |
293 """ |
276 """ |
294 if not hasattr(self, '_profile_cache'): |
277 if not hasattr(self, '_profile_cache'): |
295 from django.conf import settings |
278 from django.conf import settings |
296 if not settings.AUTH_PROFILE_MODULE: |
279 if not getattr(settings, 'AUTH_PROFILE_MODULE', False): |
297 raise SiteProfileNotAvailable |
280 raise SiteProfileNotAvailable |
298 try: |
281 try: |
299 app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.') |
282 app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.') |
300 model = models.get_model(app_label, model_name) |
283 model = models.get_model(app_label, model_name) |
301 self._profile_cache = model._default_manager.get(user__id__exact=self.id) |
284 self._profile_cache = model._default_manager.get(user__id__exact=self.id) |
|
285 self._profile_cache.user = self |
302 except (ImportError, ImproperlyConfigured): |
286 except (ImportError, ImproperlyConfigured): |
303 raise SiteProfileNotAvailable |
287 raise SiteProfileNotAvailable |
304 return self._profile_cache |
288 return self._profile_cache |
305 |
289 |
306 class Message(models.Model): |
290 class Message(models.Model): |