]> git.openstreetmap.org Git - osqa.git/blobdiff - forum/models/user.py
the mark_favorite view should accept not only Questions but any Nodes (required for...
[osqa.git] / forum / models / user.py
index ae8f9387d2d4fe82d492595eb98722ad9f2f9c63..695501f53113a531b41c67ecc97ff979bbe071a3 100644 (file)
@@ -1,9 +1,10 @@
 from base import *
 from utils import PickledObjectField
 from base import *
 from utils import PickledObjectField
+from django.conf import settings as django_settings
 from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.auth.models import User as DjangoUser, AnonymousUser as DjangoAnonymousUser
 from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.auth.models import User as DjangoUser, AnonymousUser as DjangoAnonymousUser
-from django.db.models import Q
+from django.db.models import Q, Manager
 
 from django.utils.encoding import smart_unicode
 
 
 from django.utils.encoding import smart_unicode
 
@@ -109,11 +110,25 @@ def false_if_validation_required_to(item):
         return decorated
     return decorator
 
         return decorated
     return decorator
 
+class UserManager(CachedManager):
+    def get(self, *args, **kwargs):
+        if not len(args) and len(kwargs) == 1 and 'username' in kwargs:
+            matching_users = self.filter(username=kwargs['username'])
+            
+            if len(matching_users) == 1:
+                return matching_users[0]
+            elif len(matching_users) > 1:
+                for user in matching_users:
+                    if user.username == kwargs['username']:
+                        return user
+                return matching_users[0]
+        return super(UserManager, self).get(*args, **kwargs)
+
 class User(BaseModel, DjangoUser):
     is_approved = models.BooleanField(default=False)
     email_isvalid = models.BooleanField(default=False)
 
 class User(BaseModel, DjangoUser):
     is_approved = models.BooleanField(default=False)
     email_isvalid = models.BooleanField(default=False)
 
-    reputation = models.PositiveIntegerField(default=0)
+    reputation = models.IntegerField(default=0)
     gold = models.PositiveIntegerField(default=0)
     silver = models.PositiveIntegerField(default=0)
     bronze = models.PositiveIntegerField(default=0)
     gold = models.PositiveIntegerField(default=0)
     silver = models.PositiveIntegerField(default=0)
     bronze = models.PositiveIntegerField(default=0)
@@ -130,6 +145,8 @@ class User(BaseModel, DjangoUser):
     vote_up_count = DenormalizedField("actions", canceled=False, action_type="voteup")
     vote_down_count = DenormalizedField("actions", canceled=False, action_type="votedown")
 
     vote_up_count = DenormalizedField("actions", canceled=False, action_type="voteup")
     vote_down_count = DenormalizedField("actions", canceled=False, action_type="votedown")
 
+    objects = UserManager()
+
     def __unicode__(self):
         return smart_unicode(self.username)
 
     def __unicode__(self):
         return smart_unicode(self.username)
 
@@ -176,7 +193,8 @@ class User(BaseModel, DjangoUser):
         return md5(self.email.lower()).hexdigest()
     
     def save(self, *args, **kwargs):
         return md5(self.email.lower()).hexdigest()
     
     def save(self, *args, **kwargs):
-        if self.reputation < 0:
+        # If the community doesn't allow negative reputation, set it to 0
+        if not settings.ALLOW_NEGATIVE_REPUTATION and self.reputation < 0:
             self.reputation = 0
 
         new = not bool(self.id)
             self.reputation = 0
 
         new = not bool(self.id)
@@ -198,7 +216,14 @@ class User(BaseModel, DjangoUser):
 
     @models.permalink
     def get_profile_url(self):
 
     @models.permalink
     def get_profile_url(self):
-        return ('user_profile', (), {'id': self.id, 'slug': slugify(smart_unicode(self.username))})
+        keyword_arguments = {
+            'slug': slugify(smart_unicode(self.username))
+        }
+        if settings.INCLUDE_ID_IN_USER_URLS:
+            keyword_arguments.update({
+                'id': self.id,
+            })
+        return ('user_profile', (), keyword_arguments)
 
     def get_absolute_url(self):
         return self.get_profile_url()
 
     def get_absolute_url(self):
         return self.get_profile_url()
@@ -209,7 +234,14 @@ class User(BaseModel, DjangoUser):
 
     @models.permalink
     def get_user_subscriptions_url(self):
 
     @models.permalink
     def get_user_subscriptions_url(self):
-        return ('user_subscriptions', (), { 'id': self.id, 'slug': slugify(smart_unicode(self.username))})
+        keyword_arguments = {
+            'slug': slugify(smart_unicode(self.username))
+        }
+        if settings.INCLUDE_ID_IN_USER_URLS:
+            keyword_arguments.update({
+                'id': self.id,
+            })
+        return ('user_subscriptions', (), keyword_arguments)
 
     @models.permalink
     def get_answered_url(self):
 
     @models.permalink
     def get_answered_url(self):
@@ -258,6 +290,14 @@ class User(BaseModel, DjangoUser):
         
         return votes_today
     
         
         return votes_today
     
+    def can_use_canned_comments(self):
+        # The canned comments feature is available only for admins and moderators,
+        # and only if the "Use canned comments" setting is activated in the administration.
+        if (self.is_superuser or self.is_staff) and settings.USE_CANNED_COMMENTS:
+            return True
+        else:
+            return False
+
     @true_if_is_super_or_staff
     def can_view_deleted_post(self, post):
         return post.author == self
     @true_if_is_super_or_staff
     def can_view_deleted_post(self, post):
         return post.author == self
@@ -316,8 +356,8 @@ class User(BaseModel, DjangoUser):
         return (not answer.marked) and (self.is_superuser or self.is_staff or answer.author == self or self.reputation >= int
                 (settings.REP_TO_CONVERT_TO_COMMENT))
     
         return (not answer.marked) and (self.is_superuser or self.is_staff or answer.author == self or self.reputation >= int
                 (settings.REP_TO_CONVERT_TO_COMMENT))
     
-    def can_convert_to_question(self, answer):
-        return (not answer.marked) and (self.is_superuser or self.is_staff or answer.author == self or self.reputation >= int
+    def can_convert_to_question(self, node):
+        return (not node.marked) and (self.is_superuser or self.is_staff or node.author == self or self.reputation >= int
                 (settings.REP_TO_CONVERT_TO_QUESTION))
 
     @true_if_is_super_or_staff
                 (settings.REP_TO_CONVERT_TO_QUESTION))
 
     @true_if_is_super_or_staff
@@ -353,7 +393,17 @@ class User(BaseModel, DjangoUser):
 
     @true_if_is_super_or_staff
     def can_reopen_question(self, question):
 
     @true_if_is_super_or_staff
     def can_reopen_question(self, question):
-        return self == question.author and self.reputation >= int(settings.REP_TO_REOPEN_OWN)
+        # Check whether the setting to Unify close and reopen permissions has been activated
+        if bool(settings.UNIFY_PERMISSIONS_TO_CLOSE_AND_REOPEN):
+            # If we unify close to reopen check whether the user has permissions to close.
+            # If he has -- he can reopen his question too.
+            can_reopen = (
+                self == question.author and self.reputation >= int(settings.REP_TO_CLOSE_OWN)
+            ) or self.reputation >= int(settings.REP_TO_CLOSE_OTHERS)
+        else:
+            # Check whether the user is the author and has the required permissions to reopen
+            can_reopen = self == question.author and self.reputation >= int(settings.REP_TO_REOPEN_OWN)
+        return can_reopen
 
     @true_if_is_super_or_staff
     def can_delete_post(self, post):
 
     @true_if_is_super_or_staff
     def can_delete_post(self, post):
@@ -391,7 +441,7 @@ class User(BaseModel, DjangoUser):
             except MultipleObjectsReturned:
                 logging.error("Multiple suspension actions found for user %s (%s)" % (self.username, self.id))
                 self.__dict__['_suspension_dencache_'] = self.reputes.filter(action__action_type="suspend", action__canceled=False
             except MultipleObjectsReturned:
                 logging.error("Multiple suspension actions found for user %s (%s)" % (self.username, self.id))
                 self.__dict__['_suspension_dencache_'] = self.reputes.filter(action__action_type="suspend", action__canceled=False
-                                                                             ).order_by('-action__action_date')[0]
+                                                                             ).order_by('-action__action_date')[0].action
 
         return self.__dict__['_suspension_dencache_']
 
 
         return self.__dict__['_suspension_dencache_']
 
@@ -429,7 +479,10 @@ class UserProperty(BaseModel):
     @classmethod
     def infer_cache_key(cls, querydict):
         if 'user' in querydict and 'key' in querydict:
     @classmethod
     def infer_cache_key(cls, querydict):
         if 'user' in querydict and 'key' in querydict:
-            return cls._generate_cache_key("%s:%s" % (querydict['user'].id, querydict['key']))
+            cache_key = cls._generate_cache_key("%s:%s" % (querydict['user'].id, querydict['key']))
+            if len(cache_key) > django_settings.CACHE_MAX_KEY_LENGTH:
+                cache_key = cache_key[:django_settings.CACHE_MAX_KEY_LENGTH]
+            return cache_key
 
         return None
 
 
         return None