From a4692d9cb97154ee172185efbeedc374def6dcd0 Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Tue, 1 May 2012 23:47:04 -0300 Subject: allowed admins to decide whether to moderate email posted to groups --- askbot/conf/group_settings.py | 12 + askbot/lamson_handlers.py | 7 +- ...le_moderate_email__add_field_postrevision_em.py | 322 +++++++++++++++++++++ askbot/models/__init__.py | 6 +- askbot/models/post.py | 22 +- askbot/models/question.py | 6 +- askbot/models/user.py | 1 + askbot/skins/common/media/js/post.js | 29 ++ askbot/skins/default/templates/users.html | 12 +- askbot/urls.py | 5 + askbot/utils/mail.py | 3 +- askbot/views/commands.py | 18 ++ askbot/views/users.py | 9 +- 13 files changed, 438 insertions(+), 14 deletions(-) create mode 100644 askbot/migrations/0120_auto__add_field_groupprofile_moderate_email__add_field_postrevision_em.py diff --git a/askbot/conf/group_settings.py b/askbot/conf/group_settings.py index a48fb55d..b3c0069c 100644 --- a/askbot/conf/group_settings.py +++ b/askbot/conf/group_settings.py @@ -18,3 +18,15 @@ settings.register( description = _('Enable user groups'), ) ) + +settings.register( + livesettings.BooleanValue( + GROUP_SETTINGS, + 'GROUP_EMAIL_ADDRESSES_ENABLED', + default = False, + description = _('Enable group email adddresses'), + help_text = _( + 'If selected, users can post to groups by email "group-name@domain.com"' + ) + ) +) diff --git a/askbot/lamson_handlers.py b/askbot/lamson_handlers.py index 5c86bc98..1d4bb1bc 100644 --- a/askbot/lamson_handlers.py +++ b/askbot/lamson_handlers.py @@ -3,9 +3,10 @@ from lamson.routing import route, stateless from lamson.server import Relay from django.utils.translation import ugettext as _ from django.core.files.uploadedfile import SimpleUploadedFile -from django.conf import settings +from django.conf import settings as django_settings from askbot.models import ReplyAddress, Tag from askbot.utils import mail +from askbot.conf import settings as askbot_settings #we might end up needing to use something like this @@ -122,6 +123,8 @@ def ASK(message, host = None, addr = None): if addr == 'ask': mail.process_emailed_question(from_address, subject, parts) else: + if askbot_settings.GROUP_EMAIL_ADDRESSES_ENABLED == False: + return try: group_tag = Tag.group_tags.get( deleted = False, @@ -143,7 +146,7 @@ def PROCESS(message, address = None, host = None): and make a post to askbot based on the contents of the email, including the text body and the file attachments""" try: - for rule in settings.LAMSON_FORWARD: + for rule in django_settings.LAMSON_FORWARD: if re.match(rule['pattern'], message.base['to']): relay = Relay(host=rule['host'], port=rule['port'], debug=1) diff --git a/askbot/migrations/0120_auto__add_field_groupprofile_moderate_email__add_field_postrevision_em.py b/askbot/migrations/0120_auto__add_field_groupprofile_moderate_email__add_field_postrevision_em.py new file mode 100644 index 00000000..4b9efe58 --- /dev/null +++ b/askbot/migrations/0120_auto__add_field_groupprofile_moderate_email__add_field_postrevision_em.py @@ -0,0 +1,322 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding field 'GroupProfile.moderate_email' + db.add_column('askbot_groupprofile', 'moderate_email', + self.gf('django.db.models.fields.BooleanField')(default=True), + keep_default=False) + + # Adding field 'PostRevision.email_address' + db.add_column('askbot_postrevision', 'email_address', + self.gf('django.db.models.fields.EmailField')(max_length=75, null=True, blank=True), + keep_default=False) + + def backwards(self, orm): + # Deleting field 'GroupProfile.moderate_email' + db.delete_column('askbot_groupprofile', 'moderate_email') + + # Deleting field 'PostRevision.email_address' + db.delete_column('askbot_postrevision', 'email_address') + + models = { + 'askbot.activity': { + 'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"}, + 'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Post']", 'null': 'True'}), + 'receiving_users': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'received_activity'", 'symmetrical': 'False', 'to': "orm['auth.User']"}), + 'recipients': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'incoming_activity'", 'symmetrical': 'False', 'through': "orm['askbot.ActivityAuditStatus']", 'to': "orm['auth.User']"}), + 'summary': ('django.db.models.fields.TextField', [], {'default': "''"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'askbot.activityauditstatus': { + 'Meta': {'unique_together': "(('user', 'activity'),)", 'object_name': 'ActivityAuditStatus'}, + 'activity': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Activity']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'status': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'askbot.anonymousanswer': { + 'Meta': {'object_name': 'AnonymousAnswer'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_answers'", 'to': "orm['askbot.Post']"}), + 'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}), + 'text': ('django.db.models.fields.TextField', [], {}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'askbot.anonymousquestion': { + 'Meta': {'object_name': 'AnonymousQuestion'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}), + 'is_anonymous': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'text': ('django.db.models.fields.TextField', [], {}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'askbot.award': { + 'Meta': {'object_name': 'Award', 'db_table': "u'award'"}, + 'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['askbot.BadgeData']"}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_user'", 'to': "orm['auth.User']"}) + }, + 'askbot.badgedata': { + 'Meta': {'ordering': "('slug',)", 'object_name': 'BadgeData'}, + 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'symmetrical': 'False', 'through': "orm['askbot.Award']", 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'}) + }, + 'askbot.emailfeedsetting': { + 'Meta': {'unique_together': "(('subscriber', 'feed_type'),)", 'object_name': 'EmailFeedSetting'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'feed_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'frequency': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '8'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'reported_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'subscriber': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notification_subscriptions'", 'to': "orm['auth.User']"}) + }, + 'askbot.favoritequestion': { + 'Meta': {'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Thread']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['auth.User']"}) + }, + 'askbot.groupmembership': { + 'Meta': {'object_name': 'GroupMembership'}, + 'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_memberships'", 'to': "orm['askbot.Tag']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'group_memberships'", 'to': "orm['auth.User']"}) + }, + 'askbot.groupprofile': { + 'Meta': {'object_name': 'GroupProfile'}, + 'group_tag': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'group_profile'", 'unique': 'True', 'to': "orm['askbot.Tag']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'logo_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}), + 'moderate_email': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + 'askbot.markedtag': { + 'Meta': {'object_name': 'MarkedTag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['askbot.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['auth.User']"}) + }, + 'askbot.post': { + 'Meta': {'object_name': 'Post'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'approved': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'posts'", 'to': "orm['auth.User']"}), + 'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), + 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_posts'", 'null': 'True', 'to': "orm['auth.User']"}), + 'html': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_anonymous': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_posts'", 'null': 'True', 'to': "orm['auth.User']"}), + 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'locked_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'locked_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locked_posts'", 'null': 'True', 'to': "orm['auth.User']"}), + 'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'old_answer_id': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'unique': 'True', 'null': 'True', 'blank': 'True'}), + 'old_comment_id': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'unique': 'True', 'null': 'True', 'blank': 'True'}), + 'old_question_id': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'unique': 'True', 'null': 'True', 'blank': 'True'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['askbot.Post']"}), + 'post_type': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}), + 'text': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'posts'", 'null': 'True', 'blank': 'True', 'to': "orm['askbot.Thread']"}), + 'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) + }, + 'askbot.postflagreason': { + 'Meta': {'object_name': 'PostFlagReason'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'details': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'post_reject_reasons'", 'to': "orm['askbot.Post']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '128'}) + }, + 'askbot.postrevision': { + 'Meta': {'ordering': "('-revision',)", 'unique_together': "(('post', 'revision'),)", 'object_name': 'PostRevision'}, + 'approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), + 'approved_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'approved_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'postrevisions'", 'to': "orm['auth.User']"}), + 'by_email': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'email_address': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_anonymous': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'post': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'revisions'", 'null': 'True', 'to': "orm['askbot.Post']"}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'revision_type': ('django.db.models.fields.SmallIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '125', 'blank': 'True'}), + 'text': ('django.db.models.fields.TextField', [], {}), + 'title': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '300', 'blank': 'True'}) + }, + 'askbot.questionview': { + 'Meta': {'object_name': 'QuestionView'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'viewed'", 'to': "orm['askbot.Post']"}), + 'when': ('django.db.models.fields.DateTimeField', [], {}), + 'who': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'question_views'", 'to': "orm['auth.User']"}) + }, + 'askbot.replyaddress': { + 'Meta': {'object_name': 'ReplyAddress'}, + 'address': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '25'}), + 'allowed_from_email': ('django.db.models.fields.EmailField', [], {'max_length': '150'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'post': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reply_addresses'", 'to': "orm['askbot.Post']"}), + 'response_post': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edit_addresses'", 'null': 'True', 'to': "orm['askbot.Post']"}), + 'used_at': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'askbot.repute': { + 'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"}, + 'comment': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'negative': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'positive': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Post']", 'null': 'True', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}), + 'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'askbot.tag': { + 'Meta': {'ordering': "('-used_count', 'name')", 'object_name': 'Tag', 'db_table': "u'tag'"}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['auth.User']"}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'tag_wiki': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'described_tag'", 'unique': 'True', 'null': 'True', 'to': "orm['askbot.Post']"}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'askbot.thread': { + 'Meta': {'object_name': 'Thread'}, + 'accepted_answer': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['askbot.Post']"}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'answer_accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'approved': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}), + 'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}), + 'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'unused_favorite_threads'", 'symmetrical': 'False', 'through': "orm['askbot.FavoriteQuestion']", 'to': "orm['auth.User']"}), + 'favourite_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'followed_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'followed_threads'", 'symmetrical': 'False', 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'unused_last_active_in_threads'", 'to': "orm['auth.User']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'threads'", 'symmetrical': 'False', 'to': "orm['askbot.Tag']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'view_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'askbot.vote': { + 'Meta': {'unique_together': "(('user', 'voted_post'),)", 'object_name': 'Vote', 'db_table': "u'vote'"}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['auth.User']"}), + 'vote': ('django.db.models.fields.SmallIntegerField', [], {}), + 'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'voted_post': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['askbot.Post']"}) + }, + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}), + 'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'consecutive_days_visit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'country': ('django_countries.fields.CountryField', [], {'max_length': '2', 'blank': 'True'}), + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'display_tag_filter_strategy': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'email_tag_filter_strategy': ('django.db.models.fields.SmallIntegerField', [], {'default': '1'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'gravatar': ('django.db.models.fields.CharField', [], {'max_length': '32'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ignored_tags': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'interesting_tags': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'new_response_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), + 'seen_response_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'show_country': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'w'", 'max_length': '2'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + } + } + + complete_apps = ['askbot'] \ No newline at end of file diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py index e50baf0f..9167974e 100644 --- a/askbot/models/__init__.py +++ b/askbot/models/__init__.py @@ -1342,7 +1342,8 @@ def user_post_question( wiki = False, is_anonymous = False, timestamp = None, - by_email = False + by_email = False, + email_address = None ): """makes an assertion whether user can post the question then posts it and returns the question object""" @@ -1369,7 +1370,8 @@ def user_post_question( added_at = timestamp, wiki = wiki, is_anonymous = is_anonymous, - by_email = by_email + by_email = by_email, + email_address = email_address ) question = thread._question_post() if question.author != self: diff --git a/askbot/models/post.py b/askbot/models/post.py index 89763c1f..c1fc33d6 100644 --- a/askbot/models/post.py +++ b/askbot/models/post.py @@ -24,7 +24,7 @@ import askbot from askbot.utils.slug import slugify from askbot import const from askbot.models.user import EmailFeedSetting -from askbot.models.tag import MarkedTag, tags_match_some_wildcard +from askbot.models.tag import Tag, MarkedTag, tags_match_some_wildcard from askbot.conf import settings as askbot_settings from askbot import exceptions from askbot.utils import markup @@ -1487,7 +1487,8 @@ class Post(models.Model): text = None, comment = None, revised_at = None, - by_email = False + by_email = False, + email_address = None ): if None in (author, text): raise Exception('author, text and comment are required arguments') @@ -1509,7 +1510,8 @@ class Post(models.Model): tagnames = self.thread.tagnames, summary = comment, text = text, - by_email = by_email + by_email = by_email, + email_address = email_address ) def add_revision(self, *kargs, **kwargs): @@ -1709,9 +1711,10 @@ class PostRevision(models.Model): approved = models.BooleanField(default=False, db_index=True) approved_by = models.ForeignKey(User, null = True, blank = True) - approved_at = models.DateTimeField(null= True, blank = True) + approved_at = models.DateTimeField(null = True, blank = True) - by_email = models.BooleanField(default=False)#true, if edited by email + by_email = models.BooleanField(default = False)#true, if edited by email + email_address = models.EmailField(null = True, blank = True) # Question-specific fields title = models.CharField(max_length=300, blank=True, default='') @@ -1736,6 +1739,15 @@ class PostRevision(models.Model): return False if self.approved: return False + + #if sent by email to group and group does not want moderation + if self.by_email and self.email: + group_name = self.email.split('@')[0] + try: + group = Tag.objects.get(name = group_name, deleted = False) + return group.group.profile.moderate_email + except Tag.DoesNotExist: + pass return True return False diff --git a/askbot/models/question.py b/askbot/models/question.py index de50c0c4..9481d3ac 100644 --- a/askbot/models/question.py +++ b/askbot/models/question.py @@ -71,7 +71,8 @@ class ThreadManager(models.Manager): text, tagnames = None, is_anonymous = False, - by_email = False + by_email = False, + email_address = None ): # TODO: Some of this code will go to Post.objects.create_new @@ -114,7 +115,8 @@ class ThreadManager(models.Manager): text = text, comment = const.POST_STATUS['default_version'], revised_at = added_at, - by_email = by_email + by_email = by_email, + email_address = email_address ) # INFO: Question has to be saved before update_tags() is called diff --git a/askbot/models/user.py b/askbot/models/user.py index 3c1e0ded..f4c51cdc 100644 --- a/askbot/models/user.py +++ b/askbot/models/user.py @@ -354,6 +354,7 @@ class GroupProfile(models.Model): related_name = 'group_profile' ) logo_url = models.URLField(null = True) + moderate_email = models.BooleanField(default = True) class Meta: app_label = 'askbot' diff --git a/askbot/skins/common/media/js/post.js b/askbot/skins/common/media/js/post.js index f221536a..e858413d 100644 --- a/askbot/skins/common/media/js/post.js +++ b/askbot/skins/common/media/js/post.js @@ -2248,11 +2248,40 @@ var UserGroupProfileEditor = function(){ }; inherits(UserGroupProfileEditor, TagWikiEditor); +UserGroupProfileEditor.prototype.toggleEmailModeration = function(){ + var btn = this._moderate_email_btn; + var group_id = this.getTagId(); + $.ajax({ + type: 'POST', + dataType: 'json', + cache: false, + data: {group_id: group_id}, + url: askbot['urls']['toggle_group_email_moderation'], + success: function(data){ + if (data['success']){ + btn.html(data['new_button_text']); + } else { + showMessage(btn, data['message']); + } + } + }); +}; + UserGroupProfileEditor.prototype.decorate = function(element){ UserGroupProfileEditor.superClass_.decorate.call(this, element); var change_logo_btn = element.find('.change-logo'); this._change_logo_btn = change_logo_btn; + var moderate_email_btn = element.find('.moderate-email'); + this._moderate_email_btn = moderate_email_btn; + var me = this; + setupButtonEventHandlers( + moderate_email_btn, + function(){ + me.toggleEmailModeration(); + } + ) + var logo_changer = new ImageChanger(); logo_changer.setImageElement(element.find('.group-logo')); logo_changer.setAjaxData({ diff --git a/askbot/skins/default/templates/users.html b/askbot/skins/default/templates/users.html index 9b7a282e..351a6df9 100644 --- a/askbot/skins/default/templates/users.html +++ b/askbot/skins/default/templates/users.html @@ -81,7 +81,16 @@ {% endif %} - + {% if group_email_moderation_enabled %} + | + {% if group.group_profile.moderate_email %} + {% trans %}disable moderation of emailed questions{% endtrans %} + {% else %} + {% trans %}moderate emailed questions{% endtrans %} + {% endif %} + {% endif %} {% endif %} @@ -104,6 +113,7 @@ askbot['urls']['save_tag_wiki_text'] = '{% url save_tag_wiki_text %}'; askbot['urls']['save_group_logo_url'] = '{% url save_group_logo_url %}'; askbot['urls']['delete_group_logo_url'] = '{% url delete_group_logo %}'; + askbot['urls']['toggle_group_email_moderation'] = '{% url toggle_group_email_moderation %}'; diff --git a/askbot/urls.py b/askbot/urls.py index e869d3b1..a3f694d9 100644 --- a/askbot/urls.py +++ b/askbot/urls.py @@ -212,6 +212,11 @@ urlpatterns = patterns('', views.commands.delete_group_logo, name = 'delete_group_logo' ), + url(#ajax only + r'^toggle-group-email-moderation/', + views.commands.toggle_group_email_moderation, + name = 'toggle_group_email_moderation' + ), url( r'^get-groups-list/', views.commands.get_groups_list, diff --git a/askbot/utils/mail.py b/askbot/utils/mail.py index 2d4d80b0..37245b5a 100644 --- a/askbot/utils/mail.py +++ b/askbot/utils/mail.py @@ -283,7 +283,8 @@ def process_emailed_question(from_address, subject, parts, tags = None): title = title, tags = tagnames, body_text = body_text, - by_email = True + by_email = True, + email_address = from_address ) else: raise ValidationError() diff --git a/askbot/views/commands.py b/askbot/views/commands.py index efb50974..7eeccabe 100644 --- a/askbot/views/commands.py +++ b/askbot/views/commands.py @@ -805,6 +805,24 @@ def delete_post_reject_reason(request): reason = models.PostFlagReason.objects.get(id = reason_id) reason.delete() +@csrf.csrf_exempt +@decorators.ajax_only +@decorators.post_only +@decorators.admins_only +def toggle_group_email_moderation(request): + from django.forms import IntegerField + group_id = IntegerField().clean(int(request.POST['group_id'])) + group = models.Tag.group_tags.get(id = group_id) + group.group_profile.moderate_email = not group.group_profile.moderate_email + group.group_profile.save() + if group.group_profile.moderate_email: + new_button_text = _('moderate emailed questions') + else: + new_button_text = _('disable moderation of emailed questions') + return {'new_button_text': new_button_text} + + + @csrf.csrf_exempt @decorators.ajax_only @decorators.post_only diff --git a/askbot/views/users.py b/askbot/views/users.py index b6e7d5f7..4c83a351 100644 --- a/askbot/views/users.py +++ b/askbot/views/users.py @@ -59,6 +59,7 @@ def users(request, by_group = False, group_id = None, group_slug = None): """Users view, including listing of users by group""" users = models.User.objects.all() group = None + group_email_moderation_enabled = False if by_group == True: if askbot_settings.GROUPS_ENABLED == False: raise Http404 @@ -68,6 +69,11 @@ def users(request, by_group = False, group_id = None, group_slug = None): else: try: group = models.Tag.group_tags.get(id = group_id) + group_email_moderation_enabled = \ + ( + askbot_settings.GROUP_EMAIL_ADDRESSES_ENABLED \ + and askbot_settings.ENABLE_CONTENT_MODERATION + ) except models.Tag.DoesNotExist: raise Http404 if group_slug == slugify(group.name): @@ -149,7 +155,8 @@ def users(request, by_group = False, group_id = None, group_slug = None): 'suser' : suser, 'keywords' : suser, 'tab_id' : sortby, - 'paginator_context' : paginator_context + 'paginator_context' : paginator_context, + 'group_email_moderation_enabled': group_email_moderation_enabled } return render_into_skin('users.html', data, request) -- cgit v1.2.3-1-g7c22