]> git.openstreetmap.org Git - osqa.git/blobdiff - forum/models/user.py
Avoids a strange error probably coming from either django or python.
[osqa.git] / forum / models / user.py
index 89bea283824f67b75f7bb8d9a642b3769c14befd..fb13c27f7c5524c27b2aaa544d207f76ac978a97 100644 (file)
@@ -1,4 +1,5 @@
 from base import *
 from base import *
+from utils import PickledObjectField
 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
@@ -90,6 +91,16 @@ def true_if_is_super_or_staff(fn):
 
     return decorated
 
 
     return decorated
 
+def false_if_validation_required_to(item):
+    def decorator(fn):
+        def decorated(self, *args, **kwargs):
+            if item in settings.REQUIRE_EMAIL_VALIDATION_TO and not self.email_isvalid:
+                return False
+            else:
+                return fn(self, *args, **kwargs)
+        return decorated
+    return decorator
+
 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)
@@ -114,11 +125,36 @@ class User(BaseModel, DjangoUser):
     def __unicode__(self):
         return self.username
 
     def __unicode__(self):
         return self.username
 
+    @property
+    def prop(self):
+        prop = self.__dict__.get('_prop', None)
+
+        if prop is None:
+            prop = UserPropertyDict(self)
+            self._prop = prop
+
+        return prop
+
     @property
     def is_siteowner(self):
     @property
     def is_siteowner(self):
-        #temporary thing, for now lets just assume that the site owner will always be the first user of the application
+        #todo: temporary thing, for now lets just assume that the site owner will always be the first user of the application
         return self.id == 1
 
         return self.id == 1
 
+    @property
+    def decorated_name(self):
+        if settings.SHOW_STATUS_DIAMONDS:
+            if self.is_superuser:
+                return u"%s \u2666\u2666" % self.username
+
+            if self.is_staff:
+                return u"%s \u2666" % self.username
+
+        return self.username
+
+    @property
+    def last_activity(self):
+        return self.actions.order_by('-action_date')[0].action_date
+
     @property
     def gravatar(self):
         return md5(self.email).hexdigest()
     @property
     def gravatar(self):
         return md5(self.email).hexdigest()
@@ -154,6 +190,18 @@ class User(BaseModel, DjangoUser):
     def get_absolute_url(self):
         return self.get_profile_url()
 
     def get_absolute_url(self):
         return self.get_profile_url()
 
+    @models.permalink
+    def get_asked_url(self):
+        return ('user_questions', (), {'mode': _('asked-by'), 'user': self.id, 'slug': slugify(self.username)})
+
+    @models.permalink
+    def get_answered_url(self):
+        return ('user_questions', (), {'mode': _('answered-by'), 'user': self.id, 'slug': slugify(self.username)})
+
+    @models.permalink
+    def get_subscribed_url(self):
+        return ('user_questions', (), {'mode': _('subscribed-by'), 'user': self.id, 'slug': slugify(self.username)})
+
     def get_profile_link(self):
         profile_link = u'<a href="%s">%s</a>' % (self.get_profile_url(), self.username)
         return mark_safe(profile_link)
     def get_profile_link(self):
         profile_link = u'<a href="%s">%s</a>' % (self.get_profile_url(), self.username)
         return mark_safe(profile_link)
@@ -191,6 +239,7 @@ class User(BaseModel, DjangoUser):
     def can_vote_down(self):
         return self.reputation >= int(settings.REP_TO_VOTE_DOWN)
 
     def can_vote_down(self):
         return self.reputation >= int(settings.REP_TO_VOTE_DOWN)
 
+    @false_if_validation_required_to('flag')
     def can_flag_offensive(self, post=None):
         if post is not None and post.author == self:
             return False
     def can_flag_offensive(self, post=None):
         if post is not None and post.author == self:
             return False
@@ -203,9 +252,10 @@ class User(BaseModel, DjangoUser):
         return self.reputation >= int(settings.REP_TO_VIEW_FLAGS)
 
     @true_if_is_super_or_staff
         return self.reputation >= int(settings.REP_TO_VIEW_FLAGS)
 
     @true_if_is_super_or_staff
+    @false_if_validation_required_to('comment')
     def can_comment(self, post):
         return self == post.author or self.reputation >= int(settings.REP_TO_COMMENT
     def can_comment(self, post):
         return self == post.author or self.reputation >= int(settings.REP_TO_COMMENT
-                                                             ) or (post.__class__.__name__ == "Answer" and self == post.question.author)
+                ) or (post.__class__.__name__ == "Answer" and self == post.question.author)
 
     @true_if_is_super_or_staff
     def can_like_comment(self, comment):
 
     @true_if_is_super_or_staff
     def can_like_comment(self, comment):
@@ -265,12 +315,18 @@ class User(BaseModel, DjangoUser):
             return self.can_delete_comment(post)
 
         return (self == post.author and (post.__class__.__name__ == "Answer" or
             return self.can_delete_comment(post)
 
         return (self == post.author and (post.__class__.__name__ == "Answer" or
-        not post.answers.exclude(author=self).count()))
+        not post.answers.exclude(author__id=self.id).count()))
 
     @true_if_is_super_or_staff
     def can_upload_files(self):
         return self.reputation >= int(settings.REP_TO_UPLOAD)
 
 
     @true_if_is_super_or_staff
     def can_upload_files(self):
         return self.reputation >= int(settings.REP_TO_UPLOAD)
 
+    def email_valid_and_can_ask(self):
+        return 'ask' not in settings.REQUIRE_EMAIL_VALIDATION_TO or self.email_isvalid
+
+    def email_valid_and_can_answer(self):
+        return 'answer' not in settings.REQUIRE_EMAIL_VALIDATION_TO or self.email_isvalid
+
     def check_password(self, old_passwd):
         self.__dict__.update(self.__class__.objects.filter(id=self.id).values('password')[0])
         return DjangoUser.check_password(self, old_passwd)
     def check_password(self, old_passwd):
         self.__dict__.update(self.__class__.objects.filter(id=self.id).values('password')[0])
         return DjangoUser.check_password(self, old_passwd)
@@ -279,13 +335,13 @@ class User(BaseModel, DjangoUser):
     def suspension(self):
         if self.__dict__.get('_suspension_dencache_', False) != None:
             try:
     def suspension(self):
         if self.__dict__.get('_suspension_dencache_', False) != None:
             try:
-                self.__dict__['_suspension_dencache_'] = self.actions.get(action_type="suspend", canceled=False)
+                self.__dict__['_suspension_dencache_'] = self.reputes.get(action__action_type="suspend", action__canceled=False).action
             except ObjectDoesNotExist:
                 self.__dict__['_suspension_dencache_'] = None
             except MultipleObjectsReturned:
                 logging.error("Multiple suspension actions found for user %s (%s)" % (self.username, self.id))
             except ObjectDoesNotExist:
                 self.__dict__['_suspension_dencache_'] = None
             except MultipleObjectsReturned:
                 logging.error("Multiple suspension actions found for user %s (%s)" % (self.username, self.id))
-                self.__dict__['_suspension_dencache_'] = self.actions.filter(action_type="suspend", canceled=False
-                                                                             ).order_by('-action_date')[0]
+                self.__dict__['_suspension_dencache_'] = self.reputes.filter(action__action_type="suspend", action__canceled=False
+                                                                             ).order_by('-action__action_date')[0]
 
         return self.__dict__['_suspension_dencache_']
 
 
         return self.__dict__['_suspension_dencache_']
 
@@ -308,14 +364,82 @@ class User(BaseModel, DjangoUser):
     class Meta:
         app_label = 'forum'
 
     class Meta:
         app_label = 'forum'
 
+class UserProperty(BaseModel):
+    user = models.ForeignKey(User, related_name='properties')
+    key = models.CharField(max_length=16)
+    value = PickledObjectField()
+
+    class Meta:
+        app_label = 'forum'
+        unique_together = ('user', 'key')
+
+    def cache_key(self):
+        return self._generate_cache_key("%s:%s" % (self.user.id, self.key))
+
+    @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']))
+
+        return None
+
+class UserPropertyDict(object):
+    def __init__(self, user):
+        self.__dict__['_user'] = user
+
+    def __get_property(self, name):
+        if self.__dict__.get('__%s__' % name, None):
+            return self.__dict__['__%s__' % name]
+        try:
+            user = self.__dict__['_user']
+            prop = UserProperty.objects.get(user=user, key=name)
+            self.__dict__['__%s__' % name] = prop
+            self.__dict__[name] = prop.value
+            return prop
+        except:
+            return None
+
+
+    def __getattr__(self, name):
+        if self.__dict__.get(name, None):
+            return self.__dict__[name]
+
+        prop = self.__get_property(name)
+
+        if prop:
+            return prop.value
+        else:
+            return None
+
+    def __setattr__(self, name, value):
+        current = self.__get_property(name)
+
+        if value is not None:
+            if current:
+                current.value = value
+                self.__dict__[name] = value
+                current.save(full_save=True)
+            else:
+                user = self.__dict__['_user']
+                prop = UserProperty(user=user, value=value, key=name)
+                prop.save()
+                self.__dict__[name] = value
+                self.__dict__['__%s__' % name] = prop
+        else:
+            if current:
+                current.delete()
+                del self.__dict__[name]
+                del self.__dict__['__%s__' % name]
+
+
 class SubscriptionSettings(models.Model):
 class SubscriptionSettings(models.Model):
-    user = models.OneToOneField(User, related_name='subscription_settings')
+    user = models.OneToOneField(User, related_name='subscription_settings', editable=False)
 
     enable_notifications = models.BooleanField(default=True)
 
     #notify if
     member_joins = models.CharField(max_length=1, default='n')
 
     enable_notifications = models.BooleanField(default=True)
 
     #notify if
     member_joins = models.CharField(max_length=1, default='n')
-    new_question = models.CharField(max_length=1, default='d')
+    new_question = models.CharField(max_length=1, default='n')
     new_question_watched_tags = models.CharField(max_length=1, default='i')
     subscribed_questions = models.CharField(max_length=1, default='i')
 
     new_question_watched_tags = models.CharField(max_length=1, default='i')
     subscribed_questions = models.CharField(max_length=1, default='i')
 
@@ -334,6 +458,8 @@ class SubscriptionSettings(models.Model):
     notify_comments = models.BooleanField(default=False)
     notify_accepted = models.BooleanField(default=False)
 
     notify_comments = models.BooleanField(default=False)
     notify_accepted = models.BooleanField(default=False)
 
+    send_digest = models.BooleanField(default=True)
+
     class Meta:
         app_label = 'forum'
 
     class Meta:
         app_label = 'forum'