]> git.openstreetmap.org Git - osqa.git/blobdiff - forum/models/user.py
Removed unused css selectors and a forgotten debug statement.
[osqa.git] / forum / models / user.py
index ab5941435b12ed06580972b2864be96334f8f01a..3e92e1670c6d2fa548dfc4df184a2825fbce746b 100644 (file)
@@ -1,9 +1,12 @@
 from base import *\r
 from base import *\r
-from forum import const\r
 from django.contrib.contenttypes.models import ContentType\r
 from django.contrib.auth.models import User as DjangoUser, AnonymousUser as DjangoAnonymousUser\r
 from django.db.models import Q\r
 from django.contrib.contenttypes.models import ContentType\r
 from django.contrib.auth.models import User as DjangoUser, AnonymousUser as DjangoAnonymousUser\r
 from django.db.models import Q\r
-from hashlib import md5\r
+try:\r
+    from hashlib import md5\r
+except:\r
+    from md5 import new as md5\r
+\r
 import string\r
 from random import Random\r
 \r
 import string\r
 from random import Random\r
 \r
@@ -23,7 +26,7 @@ class UserManager(CachedManager):
 \r
 class AnonymousUser(DjangoAnonymousUser):\r
     def get_visible_answers(self, question):\r
 \r
 class AnonymousUser(DjangoAnonymousUser):\r
     def get_visible_answers(self, question):\r
-        return question.answers.filter(deleted=False)\r
+        return question.answers.filter(deleted=None)\r
 \r
     def can_view_deleted_post(self, post):\r
         return False\r
 \r
     def can_view_deleted_post(self, post):\r
         return False\r
@@ -73,18 +76,19 @@ class AnonymousUser(DjangoAnonymousUser):
     def can_upload_files(self):\r
         return False\r
 \r
     def can_upload_files(self):\r
         return False\r
 \r
+def true_if_is_super_or_staff(fn):\r
+    def decorated(self, *args, **kwargs):\r
+        return self.is_superuser or self.is_staff or fn(self, *args, **kwargs)\r
+    return decorated\r
+\r
 class User(BaseModel, DjangoUser):\r
     is_approved = models.BooleanField(default=False)\r
     email_isvalid = models.BooleanField(default=False)\r
 class User(BaseModel, DjangoUser):\r
     is_approved = models.BooleanField(default=False)\r
     email_isvalid = models.BooleanField(default=False)\r
-    email_key = models.CharField(max_length=32, null=True)\r
-    reputation = models.PositiveIntegerField(default=1)\r
 \r
 \r
-    gold = models.SmallIntegerField(default=0)\r
-    silver = models.SmallIntegerField(default=0)\r
-    bronze = models.SmallIntegerField(default=0)\r
-\r
-    questions_per_page = models.SmallIntegerField(choices=QUESTIONS_PER_PAGE_CHOICES, default=10)\r
-    hide_ignored_questions = models.BooleanField(default=False)\r
+    reputation = models.PositiveIntegerField(default=0)\r
+    gold = models.PositiveIntegerField(default=0)\r
+    silver = models.PositiveIntegerField(default=0)\r
+    bronze = models.PositiveIntegerField(default=0)\r
     \r
     last_seen = models.DateTimeField(default=datetime.datetime.now)\r
     real_name = models.CharField(max_length=100, blank=True)\r
     \r
     last_seen = models.DateTimeField(default=datetime.datetime.now)\r
     real_name = models.CharField(max_length=100, blank=True)\r
@@ -92,19 +96,30 @@ class User(BaseModel, DjangoUser):
     location = models.CharField(max_length=100, blank=True)\r
     date_of_birth = models.DateField(null=True, blank=True)\r
     about = models.TextField(blank=True)\r
     location = models.CharField(max_length=100, blank=True)\r
     date_of_birth = models.DateField(null=True, blank=True)\r
     about = models.TextField(blank=True)\r
-    \r
+\r
+    subscriptions = models.ManyToManyField('Node', related_name='subscribers', through='QuestionSubscription')\r
+\r
+    vote_up_count = DenormalizedField("actions", canceled=False, action_type="voteup")\r
+    vote_down_count = DenormalizedField("actions", canceled=False, action_type="votedown")\r
+   \r
     objects = UserManager()\r
 \r
     @property\r
     def gravatar(self):\r
     objects = UserManager()\r
 \r
     @property\r
     def gravatar(self):\r
-        return hashlib.md5(self.email).hexdigest()\r
+        return md5(self.email).hexdigest()\r
 \r
     def save(self, *args, **kwargs):\r
         if self.reputation < 0:\r
 \r
     def save(self, *args, **kwargs):\r
         if self.reputation < 0:\r
-            self.reputation = 1\r
+            self.reputation = 0\r
+\r
+        new = not bool(self.id)\r
 \r
         super(User, self).save(*args, **kwargs)\r
 \r
 \r
         super(User, self).save(*args, **kwargs)\r
 \r
+        if new:\r
+            sub_settings = SubscriptionSettings(user=self)\r
+            sub_settings.save()\r
+\r
     def get_absolute_url(self):\r
         return self.get_profile_url()\r
 \r
     def get_absolute_url(self):\r
         return self.get_profile_url()\r
 \r
@@ -117,174 +132,122 @@ class User(BaseModel, DjangoUser):
     def delete_messages(self):\r
         self.message_set.all().delete()\r
 \r
     def delete_messages(self):\r
         self.message_set.all().delete()\r
 \r
+    @models.permalink\r
     def get_profile_url(self):\r
     def get_profile_url(self):\r
-        """Returns the URL for this User's profile."""\r
-        return "/%s%d/%s" % (_('users/'), self.id, slugify(self.username))\r
+        return ('user_profile', (), {'id': self.id, 'slug': slugify(self.username)})\r
 \r
     def get_profile_link(self):\r
         profile_link = u'<a href="%s">%s</a>' % (self.get_profile_url(),self.username)\r
 \r
     def get_profile_link(self):\r
         profile_link = u'<a href="%s">%s</a>' % (self.get_profile_url(),self.username)\r
-        logging.debug('in get profile link %s' % profile_link)\r
         return mark_safe(profile_link)\r
 \r
         return mark_safe(profile_link)\r
 \r
+    def get_visible_answers(self, question):\r
+        return question.answers.filter(deleted=None, in_moderation=None)\r
+\r
     def get_vote_count_today(self):\r
         today = datetime.date.today()\r
     def get_vote_count_today(self):\r
         today = datetime.date.today()\r
-        return self.votes.filter(voted_at__range=(today - datetime.timedelta(days=1), today)).count()\r
-\r
-    def get_up_vote_count(self):\r
-        return self.votes.filter(vote=1).count()\r
-\r
-    def get_down_vote_count(self):\r
-        return self.votes.filter(vote=-1).count()\r
+        return self.actions.filter(canceled=False, action_type__in=("voteup", "votedown"),\r
+                action_date__range=(today - datetime.timedelta(days=1), today)).count()\r
 \r
     def get_reputation_by_upvoted_today(self):\r
         today = datetime.datetime.now()\r
 \r
     def get_reputation_by_upvoted_today(self):\r
         today = datetime.datetime.now()\r
-        sum = self.reputes.filter(\r
-                models.Q(reputation_type=TYPE_REPUTATION_GAIN_BY_UPVOTED) |\r
-                models.Q(reputation_type=TYPE_REPUTATION_LOST_BY_UPVOTE_CANCELED),\r
-                reputed_at__range=(today - datetime.timedelta(days=1), today)).aggregate(models.Sum('value'))\r
-\r
-        if sum.get('value__sum', None) is not None: return sum['value__sum']\r
+        sum = self.reputes.filter(reputed_at__range=(today - datetime.timedelta(days=1), today)).aggregate(models.Sum('value'))\r
+        #todo: redo this, maybe transform in the daily cap\r
+        #if sum.get('value__sum', None) is not None: return sum['value__sum']\r
         return 0\r
 \r
     def get_flagged_items_count_today(self):\r
         today = datetime.date.today()\r
         return 0\r
 \r
     def get_flagged_items_count_today(self):\r
         today = datetime.date.today()\r
-        return self.flaggeditems.filter(flagged_at__range=(today - datetime.timedelta(days=1), today)).count()\r
-\r
-    def get_visible_answers(self, question):\r
-        if self.is_superuser:\r
-            return question.answers\r
-        else:\r
-            return question.answers.filter(models.Q(deleted=False) | models.Q(deleted_by=self))\r
+        return self.actions.filter(canceled=False, action_type="flag",\r
+                action_date__range=(today - datetime.timedelta(days=1), today)).count()\r
 \r
 \r
+    @true_if_is_super_or_staff\r
     def can_view_deleted_post(self, post):\r
     def can_view_deleted_post(self, post):\r
-        return self.is_superuser or post.author == self\r
+        return post.author == self\r
 \r
 \r
+    @true_if_is_super_or_staff\r
     def can_vote_up(self):\r
     def can_vote_up(self):\r
-        return self.reputation >= int(settings.REP_TO_VOTE_UP) or self.is_superuser\r
+        return self.reputation >= int(settings.REP_TO_VOTE_UP)\r
 \r
 \r
+    @true_if_is_super_or_staff\r
     def can_vote_down(self):\r
     def can_vote_down(self):\r
-        return self.reputation >= int(settings.REP_TO_VOTE_DOWN) or self.is_superuser\r
+        return self.reputation >= int(settings.REP_TO_VOTE_DOWN)\r
 \r
     def can_flag_offensive(self, post=None):\r
         if post is not None and post.author == self:\r
             return False\r
 \r
     def can_flag_offensive(self, post=None):\r
         if post is not None and post.author == self:\r
             return False\r
-        return self.is_superuser or self.reputation >= int(settings.REP_TO_FLAG)\r
+        return self.is_superuser or self.is_staff or self.reputation >= int(settings.REP_TO_FLAG)\r
 \r
 \r
+    @true_if_is_super_or_staff\r
     def can_view_offensive_flags(self, post=None):\r
         if post is not None and post.author == self:\r
             return True\r
     def can_view_offensive_flags(self, post=None):\r
         if post is not None and post.author == self:\r
             return True\r
-        return self.is_superuser or self.reputation >= int(settings.REP_TO_VIEW_FLAGS)\r
+        return self.reputation >= int(settings.REP_TO_VIEW_FLAGS)\r
 \r
 \r
+    @true_if_is_super_or_staff\r
     def can_comment(self, post):\r
         return self == post.author or self.reputation >= int(settings.REP_TO_COMMENT\r
     def can_comment(self, post):\r
         return self == post.author or self.reputation >= int(settings.REP_TO_COMMENT\r
-        ) or self.is_superuser or (post.__class__.__name__ == "Answer" and self == post.question.author)\r
+        ) or (post.__class__.__name__ == "Answer" and self == post.question.author)\r
 \r
 \r
+    @true_if_is_super_or_staff\r
     def can_like_comment(self, comment):\r
     def can_like_comment(self, comment):\r
-        return self != comment.user and (self.reputation >= int(settings.REP_TO_LIKE_COMMENT) or self.is_superuser)\r
+        return self != comment.author and (self.reputation >= int(settings.REP_TO_LIKE_COMMENT))\r
 \r
 \r
+    @true_if_is_super_or_staff\r
     def can_edit_comment(self, comment):\r
     def can_edit_comment(self, comment):\r
-        return (comment.user == self and comment.added_at >= datetime.datetime.now() - datetime.timedelta(minutes=60)\r
+        return (comment.author == self and comment.added_at >= datetime.datetime.now() - datetime.timedelta(minutes=60)\r
         ) or self.is_superuser\r
 \r
         ) or self.is_superuser\r
 \r
+    @true_if_is_super_or_staff\r
     def can_delete_comment(self, comment):\r
     def can_delete_comment(self, comment):\r
-        return self == comment.user or self.reputation >= int(settings.REP_TO_DELETE_COMMENTS) or self.is_superuser\r
+        return self == comment.author or self.reputation >= int(settings.REP_TO_DELETE_COMMENTS)\r
 \r
 \r
+    @true_if_is_super_or_staff\r
     def can_accept_answer(self, answer):\r
     def can_accept_answer(self, answer):\r
-        return self.is_superuser or self == answer.question.author\r
+        return self == answer.question.author\r
 \r
 \r
+    @true_if_is_super_or_staff\r
     def can_edit_post(self, post):\r
     def can_edit_post(self, post):\r
-        return self.is_superuser or self == post.author or self.reputation >= int(settings.REP_TO_EDIT_OTHERS\r
+        return self == post.author or self.reputation >= int(settings.REP_TO_EDIT_OTHERS\r
         ) or (post.wiki and self.reputation >= int(settings.REP_TO_EDIT_WIKI))\r
 \r
         ) or (post.wiki and self.reputation >= int(settings.REP_TO_EDIT_WIKI))\r
 \r
+    @true_if_is_super_or_staff\r
     def can_retag_questions(self):\r
         return self.reputation >= int(settings.REP_TO_RETAG)\r
 \r
     def can_retag_questions(self):\r
         return self.reputation >= int(settings.REP_TO_RETAG)\r
 \r
+    @true_if_is_super_or_staff\r
     def can_close_question(self, question):\r
     def can_close_question(self, question):\r
-        return self.is_superuser or (self == question.author and self.reputation >= int(settings.REP_TO_CLOSE_OWN)\r
+        return (self == question.author and self.reputation >= int(settings.REP_TO_CLOSE_OWN)\r
         ) or self.reputation >= int(settings.REP_TO_CLOSE_OTHERS)\r
 \r
         ) or self.reputation >= int(settings.REP_TO_CLOSE_OTHERS)\r
 \r
+    @true_if_is_super_or_staff\r
     def can_reopen_question(self, question):\r
     def can_reopen_question(self, question):\r
-        return self.is_superuser or (self == question.author and self.reputation >= settings.REP_TO_REOPEN_OWN)\r
+        return self == question.author and self.reputation >= settings.REP_TO_REOPEN_OWN\r
 \r
 \r
+    @true_if_is_super_or_staff\r
     def can_delete_post(self, post):\r
     def can_delete_post(self, post):\r
-        return self.is_superuser or (self == post.author and (post.__class__.__name__ == "Answer" or\r
-        not post.answers.filter(~Q(author=self)).count()))\r
+        if post.node_type == "comment":\r
+            return self.can_delete_comment(post)\r
+            \r
+        return (self == post.author and (post.__class__.__name__ == "Answer" or\r
+            not post.answers.exclude(author=self).count()))\r
 \r
 \r
+    @true_if_is_super_or_staff\r
     def can_upload_files(self):\r
     def can_upload_files(self):\r
-        return self.is_superuser or self.reputation >= int(settings.REP_TO_UPLOAD)\r
+        return self.reputation >= int(settings.REP_TO_UPLOAD)\r
 \r
     class Meta:\r
         app_label = 'forum'\r
 \r
 \r
     class Meta:\r
         app_label = 'forum'\r
 \r
-class Activity(GenericContent):\r
-    """\r
-    We keep some history data for user activities\r
-    """\r
-    user = models.ForeignKey(User)\r
-    activity_type = models.SmallIntegerField(choices=TYPE_ACTIVITY)\r
-    active_at = models.DateTimeField(default=datetime.datetime.now)\r
-    is_auditted    = models.BooleanField(default=False)\r
-\r
-    class Meta:\r
-        app_label = 'forum'\r
-        db_table = u'activity'\r
-\r
-    def __unicode__(self):\r
-        return u'[%s] was active at %s' % (self.user.username, self.active_at)\r
-\r
-    def save(self, *args, **kwargs):\r
-        super(Activity, self).save(*args, **kwargs)\r
-        if self._is_new:\r
-            activity_record.send(sender=self.activity_type, instance=self)\r
-\r
-    @property\r
-    def node(self):\r
-        if self.activity_type in (const.TYPE_ACTIVITY_ANSWER, const.TYPE_ACTIVITY_ASK_QUESTION,\r
-                const.TYPE_ACTIVITY_MARK_ANSWER):\r
-            return self.content_object\r
-\r
-        if self.activity_type in (const.TYPE_ACTIVITY_COMMENT_QUESTION, const.TYPE_ACTIVITY_COMMENT_ANSWER):\r
-            return self.content_object.parent.leaf\r
-\r
-        if self.activity_type in (const.TYPE_ACTIVITY_UPDATE_ANSWER, const.TYPE_ACTIVITY_UPDATE_QUESTION):\r
-            return self.content_object.node.leaf            \r
-            \r
-        raise NotImplementedError()\r
-\r
-    @property\r
-    def type_as_string(self):\r
-        if self.activity_type == const.TYPE_ACTIVITY_ASK_QUESTION:\r
-            return _("asked")\r
-        elif self.activity_type  == const.TYPE_ACTIVITY_ANSWER:\r
-            return _("answered")\r
-        elif self.activity_type  == const.TYPE_ACTIVITY_MARK_ANSWER:\r
-            return _("marked an answer")\r
-        elif self.activity_type  == const.TYPE_ACTIVITY_UPDATE_QUESTION:\r
-            return _("edited a question")\r
-        elif self.activity_type == const.TYPE_ACTIVITY_COMMENT_QUESTION:\r
-            return _("commented a question")\r
-        elif self.activity_type == const.TYPE_ACTIVITY_COMMENT_ANSWER:\r
-            return _("commented an answer")\r
-        elif self.activity_type == const.TYPE_ACTIVITY_UPDATE_ANSWER:\r
-            return _("edited an answer")\r
-        elif self.activity_type == const.TYPE_ACTIVITY_PRIZE:\r
-            return _("received badge")\r
-        else:\r
-            raise NotImplementedError()\r
-\r
-\r
-activity_record = django.dispatch.Signal(providing_args=['instance'])\r
-\r
 class SubscriptionSettings(models.Model):\r
     user = models.OneToOneField(User, related_name='subscription_settings')\r
 \r
     enable_notifications = models.BooleanField(default=True)\r
 \r
     #notify if\r
 class SubscriptionSettings(models.Model):\r
     user = models.OneToOneField(User, related_name='subscription_settings')\r
 \r
     enable_notifications = models.BooleanField(default=True)\r
 \r
     #notify if\r
-    member_joins = models.CharField(max_length=1, default='n', choices=const.NOTIFICATION_CHOICES)\r
-    new_question = models.CharField(max_length=1, default='d', choices=const.NOTIFICATION_CHOICES)\r
-    new_question_watched_tags = models.CharField(max_length=1, default='i', choices=const.NOTIFICATION_CHOICES)\r
-    subscribed_questions = models.CharField(max_length=1, default='i', choices=const.NOTIFICATION_CHOICES)\r
+    member_joins = models.CharField(max_length=1, default='n')\r
+    new_question = models.CharField(max_length=1, default='d')\r
+    new_question_watched_tags = models.CharField(max_length=1, default='i')\r
+    subscribed_questions = models.CharField(max_length=1, default='i')\r
     \r
     #auto_subscribe_to\r
     all_questions = models.BooleanField(default=False)\r
     \r
     #auto_subscribe_to\r
     all_questions = models.BooleanField(default=False)\r