~kkubasik/django/aggregation-branch

« back to all changes in this revision

Viewing changes to django/contrib/auth/models.py

  • Committer: adrian
  • Date: 2006-05-02 01:31:56 UTC
  • Revision ID: vcs-imports@canonical.com-20060502013156-2941fcd40d080649
MERGED MAGIC-REMOVAL BRANCH TO TRUNK. This change is highly backwards-incompatible. Please read http://code.djangoproject.com/wiki/RemovingTheMagic for upgrade instructions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from django.core import validators
 
2
from django.db import backend, connection, models
 
3
from django.contrib.contenttypes.models import ContentType
 
4
from django.utils.translation import gettext_lazy as _
 
5
import datetime
 
6
 
 
7
SESSION_KEY = '_auth_user_id'
 
8
 
 
9
class SiteProfileNotAvailable(Exception):
 
10
    pass
 
11
 
 
12
class Permission(models.Model):
 
13
    name = models.CharField(_('name'), maxlength=50)
 
14
    content_type = models.ForeignKey(ContentType)
 
15
    codename = models.CharField(_('codename'), maxlength=100)
 
16
    class Meta:
 
17
        verbose_name = _('permission')
 
18
        verbose_name_plural = _('permissions')
 
19
        unique_together = (('content_type', 'codename'),)
 
20
        ordering = ('content_type', 'codename')
 
21
 
 
22
    def __str__(self):
 
23
        return "%r | %s" % (self.content_type, self.name)
 
24
 
 
25
class Group(models.Model):
 
26
    name = models.CharField(_('name'), maxlength=80, unique=True)
 
27
    permissions = models.ManyToManyField(Permission, verbose_name=_('permissions'), blank=True, filter_interface=models.HORIZONTAL)
 
28
    class Meta:
 
29
        verbose_name = _('group')
 
30
        verbose_name_plural = _('groups')
 
31
        ordering = ('name',)
 
32
    class Admin:
 
33
        search_fields = ('name',)
 
34
 
 
35
    def __str__(self):
 
36
        return self.name
 
37
 
 
38
class UserManager(models.Manager):
 
39
    def create_user(self, username, email, password):
 
40
        "Creates and saves a User with the given username, e-mail and password."
 
41
        now = datetime.datetime.now()
 
42
        user = self.model(None, username, '', '', email.strip().lower(), 'placeholder', False, True, False, now, now)
 
43
        user.set_password(password)
 
44
        user.save()
 
45
        return user
 
46
 
 
47
    def make_random_password(self, length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789'):
 
48
        "Generates a random password with the given length and given allowed_chars"
 
49
        # Note that default value of allowed_chars does not have "I" or letters
 
50
        # that look like it -- just to avoid confusion.
 
51
        from random import choice
 
52
        return ''.join([choice(allowed_chars) for i in range(length)])
 
53
 
 
54
class User(models.Model):
 
55
    username = models.CharField(_('username'), maxlength=30, unique=True, validator_list=[validators.isAlphaNumeric])
 
56
    first_name = models.CharField(_('first name'), maxlength=30, blank=True)
 
57
    last_name = models.CharField(_('last name'), maxlength=30, blank=True)
 
58
    email = models.EmailField(_('e-mail address'), blank=True)
 
59
    password = models.CharField(_('password'), maxlength=128, help_text=_("Use '[algo]$[salt]$[hexdigest]'"))
 
60
    is_staff = models.BooleanField(_('staff status'), help_text=_("Designates whether the user can log into this admin site."))
 
61
    is_active = models.BooleanField(_('active'), default=True)
 
62
    is_superuser = models.BooleanField(_('superuser status'))
 
63
    last_login = models.DateTimeField(_('last login'), default=models.LazyDate())
 
64
    date_joined = models.DateTimeField(_('date joined'), default=models.LazyDate())
 
65
    groups = models.ManyToManyField(Group, verbose_name=_('groups'), blank=True,
 
66
        help_text=_("In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in."))
 
67
    user_permissions = models.ManyToManyField(Permission, verbose_name=_('user permissions'), blank=True, filter_interface=models.HORIZONTAL)
 
68
    objects = UserManager()
 
69
    class Meta:
 
70
        verbose_name = _('user')
 
71
        verbose_name_plural = _('users')
 
72
        ordering = ('username',)
 
73
    class Admin:
 
74
        fields = (
 
75
            (None, {'fields': ('username', 'password')}),
 
76
            (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
 
77
            (_('Permissions'), {'fields': ('is_staff', 'is_active', 'is_superuser', 'user_permissions')}),
 
78
            (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
 
79
            (_('Groups'), {'fields': ('groups',)}),
 
80
        )
 
81
        list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff')
 
82
        list_filter = ('is_staff', 'is_superuser')
 
83
        search_fields = ('username', 'first_name', 'last_name', 'email')
 
84
 
 
85
    def __str__(self):
 
86
        return self.username
 
87
 
 
88
    def get_absolute_url(self):
 
89
        return "/users/%s/" % self.username
 
90
 
 
91
    def is_anonymous(self):
 
92
        return False
 
93
 
 
94
    def get_full_name(self):
 
95
        full_name = '%s %s' % (self.first_name, self.last_name)
 
96
        return full_name.strip()
 
97
 
 
98
    def set_password(self, raw_password):
 
99
        import sha, random
 
100
        algo = 'sha1'
 
101
        salt = sha.new(str(random.random())).hexdigest()[:5]
 
102
        hsh = sha.new(salt+raw_password).hexdigest()
 
103
        self.password = '%s$%s$%s' % (algo, salt, hsh)
 
104
 
 
105
    def check_password(self, raw_password):
 
106
        """
 
107
        Returns a boolean of whether the raw_password was correct. Handles
 
108
        encryption formats behind the scenes.
 
109
        """
 
110
        # Backwards-compatibility check. Older passwords won't include the
 
111
        # algorithm or salt.
 
112
        if '$' not in self.password:
 
113
            import md5
 
114
            is_correct = (self.password == md5.new(raw_password).hexdigest())
 
115
            if is_correct:
 
116
                # Convert the password to the new, more secure format.
 
117
                self.set_password(raw_password)
 
118
                self.save()
 
119
            return is_correct
 
120
        algo, salt, hsh = self.password.split('$')
 
121
        if algo == 'md5':
 
122
            import md5
 
123
            return hsh == md5.new(salt+raw_password).hexdigest()
 
124
        elif algo == 'sha1':
 
125
            import sha
 
126
            return hsh == sha.new(salt+raw_password).hexdigest()
 
127
        raise ValueError, "Got unknown password algorithm type in password."
 
128
 
 
129
    def get_group_permissions(self):
 
130
        "Returns a list of permission strings that this user has through his/her groups."
 
131
        if not hasattr(self, '_group_perm_cache'):
 
132
            import sets
 
133
            cursor = connection.cursor()
 
134
            # The SQL below works out to the following, after DB quoting:
 
135
            # cursor.execute("""
 
136
            #     SELECT ct."app_label", p."codename"
 
137
            #     FROM "auth_permission" p, "auth_group_permissions" gp, "auth_user_groups" ug, "django_content_type" ct
 
138
            #     WHERE p."id" = gp."permission_id"
 
139
            #         AND gp."group_id" = ug."group_id"
 
140
            #         AND ct."id" = p."content_type_id"
 
141
            #         AND ug."user_id" = %s, [self.id])
 
142
            sql = """
 
143
                SELECT ct.%s, p.%s
 
144
                FROM %s p, %s gp, %s ug, %s ct
 
145
                WHERE p.%s = gp.%s
 
146
                    AND gp.%s = ug.%s
 
147
                    AND ct.%s = p.%s
 
148
                    AND ug.%s = %%s""" % (
 
149
                backend.quote_name('app_label'), backend.quote_name('codename'),
 
150
                backend.quote_name('auth_permission'), backend.quote_name('auth_group_permissions'),
 
151
                backend.quote_name('auth_user_groups'), backend.quote_name('django_content_type'),
 
152
                backend.quote_name('id'), backend.quote_name('permission_id'),
 
153
                backend.quote_name('group_id'), backend.quote_name('group_id'),
 
154
                backend.quote_name('id'), backend.quote_name('content_type_id'),
 
155
                backend.quote_name('user_id'),)
 
156
            cursor.execute(sql, [self.id])
 
157
            self._group_perm_cache = sets.Set(["%s.%s" % (row[0], row[1]) for row in cursor.fetchall()])
 
158
        return self._group_perm_cache
 
159
 
 
160
    def get_all_permissions(self):
 
161
        if not hasattr(self, '_perm_cache'):
 
162
            import sets
 
163
            self._perm_cache = sets.Set(["%s.%s" % (p.content_type.app_label, p.codename) for p in self.user_permissions.all()])
 
164
            self._perm_cache.update(self.get_group_permissions())
 
165
        return self._perm_cache
 
166
 
 
167
    def has_perm(self, perm):
 
168
        "Returns True if the user has the specified permission."
 
169
        if not self.is_active:
 
170
            return False
 
171
        if self.is_superuser:
 
172
            return True
 
173
        return perm in self.get_all_permissions()
 
174
 
 
175
    def has_perms(self, perm_list):
 
176
        "Returns True if the user has each of the specified permissions."
 
177
        for perm in perm_list:
 
178
            if not self.has_perm(perm):
 
179
                return False
 
180
        return True
 
181
 
 
182
    def has_module_perms(self, app_label):
 
183
        "Returns True if the user has any permissions in the given app label."
 
184
        if self.is_superuser:
 
185
            return True
 
186
        return bool(len([p for p in self.get_all_permissions() if p[:p.index('.')] == app_label]))
 
187
 
 
188
    def get_and_delete_messages(self):
 
189
        messages = []
 
190
        for m in self.message_set.all():
 
191
            messages.append(m.message)
 
192
            m.delete()
 
193
        return messages
 
194
 
 
195
    def email_user(self, subject, message, from_email=None):
 
196
        "Sends an e-mail to this User."
 
197
        from django.core.mail import send_mail
 
198
        send_mail(subject, message, from_email, [self.email])
 
199
 
 
200
    def get_profile(self):
 
201
        """
 
202
        Returns site-specific profile for this user. Raises
 
203
        SiteProfileNotAvailable if this site does not allow profiles.
 
204
        """
 
205
        if not hasattr(self, '_profile_cache'):
 
206
            from django.conf import settings
 
207
            if not settings.AUTH_PROFILE_MODULE:
 
208
                raise SiteProfileNotAvailable
 
209
            try:
 
210
                app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.')
 
211
                model = models.get_model(app_label, model_name)
 
212
                self._profile_cache = model._default_manager.get(user__id__exact=self.id)
 
213
            except ImportError, ImproperlyConfigured:
 
214
                raise SiteProfileNotAvailable
 
215
        return self._profile_cache
 
216
 
 
217
class Message(models.Model):
 
218
    user = models.ForeignKey(User)
 
219
    message = models.TextField(_('message'))
 
220
 
 
221
    def __str__(self):
 
222
        return self.message
 
223
 
 
224
class AnonymousUser(object):
 
225
    id = None
 
226
    username = ''
 
227
 
 
228
    def __init__(self):
 
229
        pass
 
230
 
 
231
    def __str__(self):
 
232
        return 'AnonymousUser'
 
233
 
 
234
    def save(self):
 
235
        raise NotImplementedError
 
236
 
 
237
    def delete(self):
 
238
        raise NotImplementedError
 
239
 
 
240
    def set_password(self, raw_password):
 
241
        raise NotImplementedError
 
242
 
 
243
    def check_password(self, raw_password):
 
244
        raise NotImplementedError
 
245
 
 
246
    def _get_groups(self):
 
247
        raise NotImplementedError
 
248
    groups = property(_get_groups)
 
249
 
 
250
    def _get_user_permissions(self):
 
251
        raise NotImplementedError
 
252
    user_permissions = property(_get_user_permissions)
 
253
 
 
254
    def has_perm(self, perm):
 
255
        return False
 
256
 
 
257
    def has_module_perms(self, module):
 
258
        return False
 
259
 
 
260
    def get_and_delete_messages(self):
 
261
        return []
 
262
 
 
263
    def is_anonymous(self):
 
264
        return True