summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdolfo Fitoria <adolfo.fitoria@gmail.com>2012-08-02 13:47:30 -0600
committerAdolfo Fitoria <adolfo.fitoria@gmail.com>2012-08-02 13:47:30 -0600
commitcfbe88a098e01297f6fd3a66364146e531d3a1c8 (patch)
tree22a46002cf4a6b15d123bf9d8630ab7ed4875163
parent4f6a78f465de5b439ece14ffea79351572dbb75d (diff)
parent9f70b5c627ba0943542127cc0b4d30b1c4f515ef (diff)
downloadaskbot-cfbe88a098e01297f6fd3a66364146e531d3a1c8.tar.gz
askbot-cfbe88a098e01297f6fd3a66364146e531d3a1c8.tar.bz2
askbot-cfbe88a098e01297f6fd3a66364146e531d3a1c8.zip
Merge branch 'master' into django1.4
-rw-r--r--askbot/conf/moderation.py9
-rw-r--r--askbot/conf/user_settings.py9
-rw-r--r--askbot/doc/source/changelog.rst1
-rw-r--r--askbot/doc/source/contributors.rst1
-rw-r--r--askbot/forms.py99
-rw-r--r--askbot/migrations/0126_add_field__auth_user__is_fake.py19
-rw-r--r--askbot/models/__init__.py57
-rw-r--r--askbot/models/base.py2
-rw-r--r--askbot/models/post.py21
-rw-r--r--askbot/models/question.py32
-rw-r--r--askbot/skins/common/media/js/post.js27
-rw-r--r--askbot/skins/common/media/js/utils.js1
-rw-r--r--askbot/skins/common/templates/widgets/edit_post.html41
-rw-r--r--askbot/skins/default/media/style/style.css4
-rw-r--r--askbot/skins/default/media/style/style.less35
-rw-r--r--askbot/skins/default/templates/answer_edit.html2
-rw-r--r--askbot/skins/default/templates/email/welcome_lamson_off.html11
-rw-r--r--askbot/skins/default/templates/macros.html3
-rw-r--r--askbot/skins/default/templates/question/new_answer_form.html2
-rw-r--r--askbot/skins/default/templates/question_edit.html3
-rw-r--r--askbot/skins/default/templates/widgets/ask_form.html3
-rw-r--r--askbot/tests/form_tests.py27
-rw-r--r--askbot/urls.py5
-rw-r--r--askbot/views/commands.py23
-rw-r--r--askbot/views/writers.py17
25 files changed, 389 insertions, 65 deletions
diff --git a/askbot/conf/moderation.py b/askbot/conf/moderation.py
index 9f8e24c7..8e77385f 100644
--- a/askbot/conf/moderation.py
+++ b/askbot/conf/moderation.py
@@ -4,8 +4,16 @@ from askbot.conf.settings_wrapper import settings
from askbot.conf.super_groups import DATA_AND_FORMATTING
from askbot.deps.livesettings import ConfigurationGroup
from askbot.deps.livesettings import BooleanValue
+from django.core.cache import cache
from django.utils.translation import ugettext as _
+def empty_cache_callback(old_value, new_value):
+ """used to clear cache on change of certain values"""
+ if old_value != new_value:
+ #todo: change this to warmup cache
+ cache.clear()
+ return new_value
+
MODERATION = ConfigurationGroup(
'MODERATION',
_('Content moderation'),
@@ -18,5 +26,6 @@ settings.register(
'ENABLE_CONTENT_MODERATION',
default = False,
description = _('Enable content moderation'),
+ update_callback = empty_cache_callback
)
)
diff --git a/askbot/conf/user_settings.py b/askbot/conf/user_settings.py
index 9077a720..e7dea7c8 100644
--- a/askbot/conf/user_settings.py
+++ b/askbot/conf/user_settings.py
@@ -16,6 +16,15 @@ USER_SETTINGS = livesettings.ConfigurationGroup(
)
settings.register(
+ livesettings.StringValue(
+ USER_SETTINGS,
+ 'NEW_USER_GREETING',
+ default = '',
+ description = _('On-screen greeting shown to the new users')
+ )
+)
+
+settings.register(
livesettings.BooleanValue(
USER_SETTINGS,
'EDITABLE_SCREEN_NAME',
diff --git a/askbot/doc/source/changelog.rst b/askbot/doc/source/changelog.rst
index c0540be9..48725c07 100644
--- a/askbot/doc/source/changelog.rst
+++ b/askbot/doc/source/changelog.rst
@@ -6,6 +6,7 @@ Development version
* Added optional support for unicode slugs (Evgeny)
* Optionally allow limiting one answer per question per person (Evgeny)
* Added management command `build_livesettings_cache` (Adolfo)
+* Administrators can post under fictional user accounts without logging out (jtrain, Evgeny)
* Welcome email for the case when replying by email is enabled (Evgeny)
* Detection of email signature based on the response to the welcome email (Evgeny)
* Hide "website" and "about" section of the blocked user profiles
diff --git a/askbot/doc/source/contributors.rst b/askbot/doc/source/contributors.rst
index 69348b84..ce8656ea 100644
--- a/askbot/doc/source/contributors.rst
+++ b/askbot/doc/source/contributors.rst
@@ -41,6 +41,7 @@ Programming and documentation
* Silvio Heuberger
* `Alexandros <https://github.com/alexandros-z>`_
* `Paul Backhouse <https://github.com/powlo>`_
+* `jtrain <https://github.com/jtrain>`_
Translations
------------
diff --git a/askbot/forms.py b/askbot/forms.py
index 1188ed59..ecf86717 100644
--- a/askbot/forms.py
+++ b/askbot/forms.py
@@ -3,6 +3,7 @@ used in AskBot"""
import re
from django import forms
from askbot import const
+from django.forms.util import ErrorList
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ungettext_lazy, string_concat
from django.utils.text import get_text_list
@@ -733,7 +734,80 @@ class FormWithHideableFields(object):
self.fields[name] = self.__hidden_fields.pop(name)
-class AskForm(forms.Form, FormWithHideableFields):
+class PostAsSomeoneForm(forms.Form):
+ post_author_username = forms.CharField(
+ initial=_('User name:'),
+ help_text=_(
+ 'Enter name to post on behalf of someone else. '
+ 'Can create new accounts.'
+ ),
+ required=False,
+ widget=forms.TextInput(attrs={'class': 'tipped-input'})
+ )
+ post_author_email = forms.CharField(
+ initial=_('Email address:'),
+ required=False,
+ widget=forms.TextInput(attrs={'class': 'tipped-input'})
+ )
+
+ def get_post_user(self, user):
+ """returns user on whose behalf the post or a revision
+ is being made
+ """
+ username = self.cleaned_data['post_author_username']
+ email= self.cleaned_data['post_author_email']
+ if user.is_administrator() and username and email:
+ post_user = user.get_or_create_fake_user(username, email)
+ else:
+ post_user = user
+ return post_user
+
+ def clean_post_author_username(self):
+ """if value is the same as initial, it is reset to
+ empty string
+ todo: maybe better to have field where initial value is invalid,
+ then we would not have to have two almost identical clean functions?
+ """
+ username = self.cleaned_data.get('post_author_username', '')
+ initial_username = unicode(self.fields['post_author_username'].initial)
+ if username == initial_username:
+ self.cleaned_data['post_author_username'] = ''
+ return self.cleaned_data['post_author_username']
+
+ def clean_post_author_email(self):
+ """if value is the same as initial, it is reset to
+ empty string"""
+ email = self.cleaned_data.get('post_author_email', '')
+ initial_email = unicode(self.fields['post_author_email'].initial)
+ if email == initial_email:
+ email = ''
+ if email != '':
+ email = forms.EmailField().clean(email)
+ self.cleaned_data['post_author_email'] = email
+ return email
+
+ def clean(self):
+ """requires email address if user name is given"""
+ username = self.cleaned_data.get('post_author_username', '')
+ email = self.cleaned_data.get('post_author_email', '')
+ if username == '' and email:
+ username_errors = self._errors.get(
+ 'post_author_username',
+ ErrorList()
+ )
+ username_errors.append(_('User name is required with the email'))
+ self._errors['post_author_username'] = username_errors
+ raise forms.ValidationError('missing user name')
+ elif email == '' and username:
+ email_errors = self._errors.get('post_author_email', ErrorList())
+ email_errors.append(_('Email is required if user name is added'))
+ self._errors['post_author_email'] = email_errors
+ raise forms.ValidationError('missing email')
+
+ return self.cleaned_data
+
+
+class AskForm(PostAsSomeoneForm, FormWithHideableFields):
"""the form used to askbot questions
field ask_anonymously is shown to the user if the
if ALLOW_ASK_ANONYMOUSLY live setting is True
@@ -757,14 +831,6 @@ class AskForm(forms.Form, FormWithHideableFields):
required=False, max_length=255,
widget=forms.TextInput(attrs={'size': 40, 'class': 'openid-input'})
)
- user = forms.CharField(
- required=False, max_length=255,
- widget=forms.TextInput(attrs={'size': 35})
- )
- email = forms.CharField(
- required=False, max_length=255,
- widget=forms.TextInput(attrs={'size': 35})
- )
def __init__(self, *args, **kwargs):
super(AskForm, self).__init__(*args, **kwargs)
@@ -867,21 +933,13 @@ class AskByEmailForm(forms.Form):
return self.cleaned_data['subject']
-class AnswerForm(forms.Form):
+class AnswerForm(PostAsSomeoneForm):
text = AnswerEditorField()
wiki = WikiField()
openid = forms.CharField(
required=False, max_length=255,
widget=forms.TextInput(attrs={'size': 40, 'class': 'openid-input'})
)
- user = forms.CharField(
- required=False, max_length=255,
- widget=forms.TextInput(attrs={'size': 35})
- )
- email = forms.CharField(
- required=False, max_length=255,
- widget=forms.TextInput(attrs={'size': 35})
- )
email_notify = EmailNotifyField(initial=False)
def __init__(self, *args, **kwargs):
@@ -952,7 +1010,7 @@ class RevisionForm(forms.Form):
self.fields['revision'].initial = latest_revision.revision
-class EditQuestionForm(forms.Form, FormWithHideableFields):
+class EditQuestionForm(PostAsSomeoneForm, FormWithHideableFields):
title = TitleField()
text = QuestionEditorField()
tags = TagNamesField()
@@ -1053,6 +1111,7 @@ class EditQuestionForm(forms.Form, FormWithHideableFields):
field edit_anonymously. It relies on correct cleaning
if the "reveal_identity" field
"""
+ super(EditQuestionForm, self).clean()
reveal_identity = self.cleaned_data.get('reveal_identity', False)
stay_anonymous = False
if reveal_identity is False and self.can_stay_anonymous():
@@ -1061,7 +1120,7 @@ class EditQuestionForm(forms.Form, FormWithHideableFields):
return self.cleaned_data
-class EditAnswerForm(forms.Form):
+class EditAnswerForm(PostAsSomeoneForm):
text = AnswerEditorField()
summary = SummaryField()
wiki = WikiField()
diff --git a/askbot/migrations/0126_add_field__auth_user__is_fake.py b/askbot/migrations/0126_add_field__auth_user__is_fake.py
new file mode 100644
index 00000000..e0928ed7
--- /dev/null
+++ b/askbot/migrations/0126_add_field__auth_user__is_fake.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+from south.db import db
+from south.v2 import SchemaMigration
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ try:
+ # Adding field 'User.is_fake'
+ db.add_column(
+ u'auth_user', 'is_fake',
+ self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False)
+ except:
+ pass
+
+ def backwards(self, orm):
+ db.delete_column('auth_user', 'is_fake')
+
+ complete_apps = ['askbot']
diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py
index 1c884ed6..c1beb594 100644
--- a/askbot/models/__init__.py
+++ b/askbot/models/__init__.py
@@ -83,6 +83,7 @@ User.add_to_class(
choices = const.USER_STATUS_CHOICES
)
)
+User.add_to_class('is_fake', models.BooleanField(default=False))
User.add_to_class('email_isvalid', models.BooleanField(default=False)) #@UndefinedVariable
User.add_to_class('email_key', models.CharField(max_length=32, null=True))
@@ -343,6 +344,24 @@ def user_can_post_by_email(self):
return askbot_settings.REPLY_BY_EMAIL and \
self.reputation > askbot_settings.MIN_REP_TO_POST_BY_EMAIL
+def user_get_or_create_fake_user(self, username, email):
+ """
+ Get's or creates a user, most likely with the purpose
+ of posting under that account.
+ """
+ assert(self.is_administrator())
+
+ try:
+ user = User.objects.get(username=username)
+ except User.DoesNotExist:
+ user = User()
+ user.username = username
+ user.email = email
+ user.is_fake = True
+ user.set_unusable_password()
+ user.save()
+ return user
+
def _assert_user_can(
user = None,
post = None, #related post (may be parent)
@@ -2172,14 +2191,14 @@ def user_get_badge_summary(self):
bit = ungettext(
'one silver badge',
'%(count)d silver badges',
- self.gold
+ self.silver
) % {'count': self.silver}
badge_bits.append(bit)
- if self.silver:
+ if self.bronze:
bit = ungettext(
'one bronze badge',
'%(count)d bronze badges',
- self.gold
+ self.bronze
) % {'count': self.bronze}
badge_bits.append(bit)
@@ -2537,6 +2556,7 @@ User.add_to_class('get_absolute_url', user_get_absolute_url)
User.add_to_class('get_avatar_url', user_get_avatar_url)
User.add_to_class('get_default_avatar_url', user_get_default_avatar_url)
User.add_to_class('get_gravatar_url', user_get_gravatar_url)
+User.add_to_class('get_or_create_fake_user', user_get_or_create_fake_user)
User.add_to_class('get_marked_tags', user_get_marked_tags)
User.add_to_class('get_marked_tag_names', user_get_marked_tag_names)
User.add_to_class('strip_email_signature', user_strip_email_signature)
@@ -2844,7 +2864,7 @@ def send_instant_notifications_about_activity_in_post(
newly mentioned users are carried through to reduce
database hits
"""
- if askbot_settings.ENABLE_CONTENT_MODERATION and post.approved == False:
+ if post.is_approved() is False:
return
if recipients is None:
@@ -3215,22 +3235,29 @@ def send_respondable_email_validation_message(
)
-def send_welcome_email(user, **kwargs):
+def greet_new_user(user, **kwargs):
"""sends welcome email to the newly created user
todo: second branch should send email with a simple
clickable link.
"""
+ if askbot_settings.NEW_USER_GREETING:
+ user.message_set.create(message = askbot_settings.NEW_USER_GREETING)
+
if askbot_settings.REPLY_BY_EMAIL:#with this on we also collect signature
- data = {
- 'site_name': askbot_settings.APP_SHORT_NAME
- }
- send_respondable_email_validation_message(
- user = user,
- subject_line = _('Welcome to %(site_name)s') % data,
- data = data,
- template_name = 'email/welcome_lamson_on.html'
- )
+ template_name = 'email/welcome_lamson_on.html'
+ else:
+ template_name = 'email/welcome_lamson_off.html'
+
+ data = {
+ 'site_name': askbot_settings.APP_SHORT_NAME
+ }
+ send_respondable_email_validation_message(
+ user = user,
+ subject_line = _('Welcome to %(site_name)s') % data,
+ data = data,
+ template_name = template_name
+ )
def complete_pending_tag_subscriptions(sender, request, *args, **kwargs):
@@ -3317,7 +3344,7 @@ signals.delete_question_or_answer.connect(record_delete_question, sender=Post)
signals.flag_offensive.connect(record_flag_offensive, sender=Post)
signals.remove_flag_offensive.connect(remove_flag_offensive, sender=Post)
signals.tags_updated.connect(record_update_tags)
-signals.user_registered.connect(send_welcome_email)
+signals.user_registered.connect(greet_new_user)
signals.user_updated.connect(record_user_full_updated, sender=User)
signals.user_logged_in.connect(complete_pending_tag_subscriptions)#todo: add this to fake onlogin middleware
signals.user_logged_in.connect(post_anonymous_askbot_content)
diff --git a/askbot/models/base.py b/askbot/models/base.py
index b3a12fbf..74b8c2dd 100644
--- a/askbot/models/base.py
+++ b/askbot/models/base.py
@@ -41,7 +41,7 @@ class BaseQuerySetManager(models.Manager):
return getattr(self.get_query_set(), attr, *args)
-class AnonymousContent(models.Model):
+class DraftContent(models.Model):
"""Base class for AnonymousQuestion and AnonymousAnswer"""
session_key = models.CharField(max_length=40) #session id for anonymous questions
wiki = models.BooleanField(default=False)
diff --git a/askbot/models/post.py b/askbot/models/post.py
index d61c1ae2..25b3f47a 100644
--- a/askbot/models/post.py
+++ b/askbot/models/post.py
@@ -29,7 +29,7 @@ from askbot.conf import settings as askbot_settings
from askbot import exceptions
from askbot.utils import markup
from askbot.utils.html import sanitize_html
-from askbot.models.base import BaseQuerySetManager, AnonymousContent
+from askbot.models.base import BaseQuerySetManager, DraftContent
#todo: maybe merge askbot.utils.markup and forum.utils.html
from askbot.utils.diff import textDiff as htmldiff
@@ -513,8 +513,18 @@ class Post(models.Model):
def is_reject_reason(self):
return self.post_type == 'reject_reason'
+ def is_approved(self):
+ """``False`` only when moderation is ``True`` and post
+ ``self.approved is False``
+ """
+ if askbot_settings.ENABLE_CONTENT_MODERATION:
+ if self.approved == False:
+ return False
+ return True
+
def needs_moderation(self):
- return self.approved == False
+ #todo: do we need this, can't we just use is_approved()?
+ return self.approved is False
def get_absolute_url(self, no_slug = False, question_post=None, thread=None):
from askbot.utils.slug import slugify
@@ -1207,9 +1217,8 @@ class Post(models.Model):
def _question__assert_is_visible_to(self, user):
"""raises QuestionHidden"""
- if askbot_settings.ENABLE_CONTENT_MODERATION:
- if self.approved == False:
- raise exceptions.QuestionHidden()
+ if self.is_approved() is False:
+ raise exceptions.QuestionHidden()
if self.deleted:
message = _(
'Sorry, this question has been '
@@ -1897,7 +1906,7 @@ class PostFlagReason(models.Model):
app_label = 'askbot'
-class AnonymousAnswer(AnonymousContent):
+class AnonymousAnswer(DraftContent):
question = models.ForeignKey(Post, related_name='anonymous_answers')
def publish(self, user):
diff --git a/askbot/models/question.py b/askbot/models/question.py
index 3e8d2267..2bb9e80a 100644
--- a/askbot/models/question.py
+++ b/askbot/models/question.py
@@ -14,7 +14,7 @@ from django.utils.translation import ungettext
import askbot
import askbot.conf
from askbot.models.tag import Tag
-from askbot.models.base import AnonymousContent
+from askbot.models.base import DraftContent
from askbot.models.post import Post, PostRevision
from askbot.models import signals
from askbot import const
@@ -580,7 +580,7 @@ class Thread(models.Model):
#pass through only deleted question posts
if post.deleted and post.post_type != 'question':
continue
- if post.approved == False:#hide posts on the moderation queue
+ if post.is_approved() is False:#hide posts on the moderation queue
continue
post_to_author[post.id] = post.author_id
@@ -641,6 +641,8 @@ class Thread(models.Model):
"""
def get_data():
+ # todo: code in this function would be simpler if
+ # we had question post id denormalized on the thread
tags_list = self.get_tag_names()
similar_threads = Thread.objects.filter(
tags__name__in=tags_list
@@ -659,20 +661,28 @@ class Thread(models.Model):
similar_threads = similar_threads[:10]
# Denormalize questions to speed up template rendering
+ # todo: just denormalize question_post_id on the thread!
thread_map = dict([(thread.id, thread) for thread in similar_threads])
questions = Post.objects.get_questions()
questions = questions.select_related('thread').filter(thread__in=similar_threads)
for q in questions:
thread_map[q.thread_id].question_denorm = q
- # Postprocess data
- similar_threads = [
- {
- 'url': thread.question_denorm.get_absolute_url(),
- 'title': thread.get_title(thread.question_denorm)
- } for thread in similar_threads
- ]
- return similar_threads
+ # Postprocess data for the final output
+ result = list()
+ for thread in similar_threads:
+ question_post = getattr(thread, 'question_denorm', None)
+ # unfortunately the if statement below is necessary due to
+ # a possible bug
+ # all this proves that it's wrong to reference threads by
+ # the question post id in the question page urls!!!
+ # this is a "legacy" problem inherited from the old models
+ if question_post:
+ url = question_post.get_absolute_url()
+ title = thread.get_title(question_post)
+ result.append({'url': url, 'title': title})
+
+ return result
def get_cached_data():
"""similar thread data will expire
@@ -919,7 +929,7 @@ class FavoriteQuestion(models.Model):
return '[%s] favorited at %s' %(self.user, self.added_at)
-class AnonymousQuestion(AnonymousContent):
+class AnonymousQuestion(DraftContent):
"""question that was asked before logging in
maybe the name is a little misleading, the user still
may or may not want to stay anonymous after the question
diff --git a/askbot/skins/common/media/js/post.js b/askbot/skins/common/media/js/post.js
index 58f2436d..32453212 100644
--- a/askbot/skins/common/media/js/post.js
+++ b/askbot/skins/common/media/js/post.js
@@ -2408,6 +2408,33 @@ $(document).ready(function() {
});
questionRetagger.init();
socialSharing.init();
+
+ var proxyUserNameInput = $('#id_post_author_username');
+ var proxyUserEmailInput = $('#id_post_author_email');
+ if (proxyUserNameInput.length === 1) {
+ var tip = new TippedInput();
+ tip.decorate(proxyUserNameInput);
+
+ var userSelectHandler = function(data) {
+ proxyUserEmailInput.val(data['data'][0]);
+ };
+
+ var fakeUserAc = new AutoCompleter({
+ url: '/get-users-info/',//askbot['urls']['get_users_info'],
+ preloadData: true,
+ minChars: 1,
+ useCache: true,
+ matchInside: true,
+ maxCacheLength: 100,
+ delay: 10,
+ onItemSelect: userSelectHandler
+ });
+ fakeUserAc.decorate(proxyUserNameInput);
+ }
+ if (proxyUserEmailInput.length === 1) {
+ var tip = new TippedInput();
+ tip.decorate(proxyUserEmailInput);
+ }
});
diff --git a/askbot/skins/common/media/js/utils.js b/askbot/skins/common/media/js/utils.js
index 81aff7c3..3f585435 100644
--- a/askbot/skins/common/media/js/utils.js
+++ b/askbot/skins/common/media/js/utils.js
@@ -313,6 +313,7 @@ TippedInput.prototype.decorate = function(element){
this._element = element;
var instruction_text = this.getVal();
this._instruction = instruction_text;
+ this.reset();
var me = this;
$(element).focus(function(){
if (me.isBlank()){
diff --git a/askbot/skins/common/templates/widgets/edit_post.html b/askbot/skins/common/templates/widgets/edit_post.html
index 66f79237..f26e57f6 100644
--- a/askbot/skins/common/templates/widgets/edit_post.html
+++ b/askbot/skins/common/templates/widgets/edit_post.html
@@ -18,7 +18,7 @@
{% if post_type == 'question' %}
<div class="form-item">
{% if tags_are_required %}
- <label for=id_tags">
+ <label for="id_tags">
{% if mandatory_tags %}
<strong>{% trans %}tags{% endtrans %}</strong>
{% trans %}, one of these is required{% endtrans %}
@@ -54,6 +54,7 @@
<div class="form-error" >{{ post_form.summary.errors }}</div>
</div>
{% endif %}
+
<div class="preview-toggle">
<span
id="pre-collapse"
@@ -63,3 +64,41 @@
</span>
</div>
<div id="previewer" class="wmd-preview"></div>
+
+{% if user and user.is_authenticated() and user.is_administrator() %}
+ {# admin can post answers or questions on behalf of anyone. #}
+ <table class="proxy-user-info">
+ <tbody>
+ <tr><td colspan="2">
+ <label>
+ {% trans %}To post on behalf of someone else, enter user name <strong>and</strong> email below.{% endtrans %}
+ </label>
+ </td></tr>
+ <tr>
+ <td>
+ <div class="form-item">
+ {{ post_form.post_author_username }}
+ <!--input
+ id="id_post_author_username"
+ name="post_author_username"
+ value="{% trans %}User name:{% endtrans %}"
+ /-->
+ </div>
+ <div class="form-item">
+ {{ post_form.post_author_email }}
+ <!--input
+ id="id_post_author_email"
+ name="post_author_email"
+ value="{% trans %}Email address:{% endtrans %}"
+ /-->
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <span class="form-error">{{ post_form.post_author_username.errors }}</span>
+ <span class="form-error">{{ post_form.post_author_email.errors }}</span>
+ </td>
+ </tbody>
+ </table>
+{% endif %}
diff --git a/askbot/skins/default/media/style/style.css b/askbot/skins/default/media/style/style.css
index 7a695825..c8d92f60 100644
--- a/askbot/skins/default/media/style/style.css
+++ b/askbot/skins/default/media/style/style.css
@@ -1358,7 +1358,9 @@ ul#related-tags li {
font-size: 13px;
}
.ask-page #id_tags,
-.edit-question-page #id_tags {
+.edit-question-page #id_tags,
+#id_user,
+#id_user_author {
border: #cce6ec 3px solid;
height: 25px;
padding-left: 5px;
diff --git a/askbot/skins/default/media/style/style.less b/askbot/skins/default/media/style/style.less
index 4e272eca..db5d14f8 100644
--- a/askbot/skins/default/media/style/style.less
+++ b/askbot/skins/default/media/style/style.less
@@ -1345,13 +1345,46 @@ ul#related-tags li {
font-size:13px;
}
- #id_tags{
+ #id_tags {
border:#cce6ec 3px solid;
height:25px;
padding-left:5px;
+ font-size:14px;
width:395px;
+ }
+}
+
+.ask-page,
+.question-page,
+.edit-question-page,
+.edit-answer-page {
+ #id_post_author_username,
+ #id_post_author_email {
+ border:#cce6ec 3px solid;
+ height:25px;
+ padding-left:5px;
font-size:14px;
+ width:186px;
}
+ #id_post_author_email {
+ margin-left: 10px;
+ }
+ table.proxy-user-info {
+ border-spacing: 0px;
+
+ .form-item {
+ float: left;
+ }
+ }
+}
+
+#id_user,
+#id_user_author {
+ border:#cce6ec 3px solid;
+ height:25px;
+ padding-left:5px;
+ width:395px;
+ font-size:14px;
}
.title-desc {
diff --git a/askbot/skins/default/templates/answer_edit.html b/askbot/skins/default/templates/answer_edit.html
index bbc00420..a1dbb4f9 100644
--- a/askbot/skins/default/templates/answer_edit.html
+++ b/askbot/skins/default/templates/answer_edit.html
@@ -16,7 +16,7 @@
<div style="vertical-align:middle">
{{ revision_form.revision }} <input type="submit" style="display:none" id="select_revision" name="select_revision" value="{% trans %}select revision{% endtrans %}">
</div>
- {{ macros.edit_post(form) }}
+ {{ macros.edit_post(form, user = request.user) }}
{% if settings.WIKI_ON and answer.wiki == False %}
{{ macros.checkbox_in_div(form.wiki) }}
{% endif %}
diff --git a/askbot/skins/default/templates/email/welcome_lamson_off.html b/askbot/skins/default/templates/email/welcome_lamson_off.html
new file mode 100644
index 00000000..d1b9854d
--- /dev/null
+++ b/askbot/skins/default/templates/email/welcome_lamson_off.html
@@ -0,0 +1,11 @@
+{% import "email/macros.html" as macros %}
+{# site_name - is short name of the site, email_code - address portion
+of the reply email used for this message, we scan to the last appearance
+of the email code to detect the response signature that will appear under #}
+<p style="{{ macros.heading_style() }}">
+ {% trans %}Welcome to {{ site_name }}!{% endtrans %}
+</p>
+<p>
+ {% trans %}We look forward to your Questions!{% endtrans %}
+</p>
+{% include "email/footer.html" %}
diff --git a/askbot/skins/default/templates/macros.html b/askbot/skins/default/templates/macros.html
index 261c860f..4cc4e081 100644
--- a/askbot/skins/default/templates/macros.html
+++ b/askbot/skins/default/templates/macros.html
@@ -479,7 +479,8 @@ for the purposes of the AJAX comment editor #}
post_form,
post_type = None,
mandatory_tags = None,
- edit_title = False
+ edit_title = False,
+ user = None
)
-%}
{%include "widgets/edit_post.html" %}
diff --git a/askbot/skins/default/templates/question/new_answer_form.html b/askbot/skins/default/templates/question/new_answer_form.html
index 68af8afb..9868d3ba 100644
--- a/askbot/skins/default/templates/question/new_answer_form.html
+++ b/askbot/skins/default/templates/question/new_answer_form.html
@@ -39,7 +39,7 @@
{% endif %}
</p>
{% endif %}
- {{ macros.edit_post(answer) }}
+ {{ macros.edit_post(answer, user = request.user) }}
<input id="add-answer-btn" type="submit" class="submit after-editor" style="float:left"/>
<script type="text/javascript">
askbot['functions']['renderAddAnswerButton']();
diff --git a/askbot/skins/default/templates/question_edit.html b/askbot/skins/default/templates/question_edit.html
index 47873e0e..adf2f35b 100644
--- a/askbot/skins/default/templates/question_edit.html
+++ b/askbot/skins/default/templates/question_edit.html
@@ -20,7 +20,8 @@
form,
post_type='question',
edit_title=True,
- mandatory_tags = mandatory_tags
+ mandatory_tags = mandatory_tags,
+ user = request.user
)
}}
<div class="after-editor">
diff --git a/askbot/skins/default/templates/widgets/ask_form.html b/askbot/skins/default/templates/widgets/ask_form.html
index b8a5ce2c..2ece84d5 100644
--- a/askbot/skins/default/templates/widgets/ask_form.html
+++ b/askbot/skins/default/templates/widgets/ask_form.html
@@ -26,7 +26,8 @@
form,
post_type = 'question',
edit_title = False,
- mandatory_tags = mandatory_tags
+ mandatory_tags = mandatory_tags,
+ user = request.user
)
}}
<div class="question-options">
diff --git a/askbot/tests/form_tests.py b/askbot/tests/form_tests.py
index 654272b3..a37f380c 100644
--- a/askbot/tests/form_tests.py
+++ b/askbot/tests/form_tests.py
@@ -334,3 +334,30 @@ class AnswerEditorFieldTests(AskbotTestCase):
self.field.clean(10*'a'),
10*'a'
)
+
+
+class PostAsSomeoneFormTests(AskbotTestCase):
+
+ form = forms.PostAsSomeoneForm
+
+ def setUp(self):
+ self.good_data = {
+ 'username': 'me',
+ 'email': 'me@example.com'
+ }
+
+ def test_blank_form_validates(self):
+ form = forms.PostAsSomeoneForm({})
+ self.assertEqual(form.is_valid(), True)
+
+ def test_complete_form_validates(self):
+ form = forms.PostAsSomeoneForm(self.good_data)
+ self.assertEqual(form.is_valid(), True)
+
+ def test_missing_email_fails(self):
+ form = forms.PostAsSomeoneForm({'post_author_username': 'me'})
+ self.assertEqual(form.is_valid(), False)
+
+ def test_missing_username_fails(self):
+ form = forms.PostAsSomeoneForm({'post_author_email': 'me@example.com'})
+ self.assertEqual(form.is_valid(), False)
diff --git a/askbot/urls.py b/askbot/urls.py
index 869f7d69..f39371e5 100644
--- a/askbot/urls.py
+++ b/askbot/urls.py
@@ -79,6 +79,11 @@ urlpatterns = patterns('',
name = 'api_get_questions'
),
url(
+ r'^get-users-info/',
+ views.commands.get_users_info,
+ name='get_users_info'
+ ),
+ url(
r'^%s%s$' % (_('questions/'), _('ask/')),
views.writers.ask,
name='ask'
diff --git a/askbot/views/commands.py b/askbot/views/commands.py
index e343c85e..12305f46 100644
--- a/askbot/views/commands.py
+++ b/askbot/views/commands.py
@@ -913,3 +913,26 @@ def save_post_reject_reason(request):
}
else:
raise Exception(forms.format_form_errors(form))
+
+
+@decorators.get_only
+@decorators.admins_only
+def get_users_info(request):
+ """retuns list of user names and email addresses
+ of "fake" users - so that admins can post on their
+ behalf"""
+ user_info_list = models.User.objects.filter(
+ is_fake=True
+ ).values_list(
+ 'username',
+ 'email'
+ )
+
+ result_list = list()
+ for user_info in user_info_list:
+ username = user_info[0]
+ email = user_info[1]
+ result_list.append('%s|%s' % (username, email))
+
+ output = '\n'.join(result_list)
+ return HttpResponse(output, mimetype = 'text/plain')
diff --git a/askbot/views/writers.py b/askbot/views/writers.py
index 9a2de128..6bda3782 100644
--- a/askbot/views/writers.py
+++ b/askbot/views/writers.py
@@ -15,6 +15,7 @@ import time
import urlparse
from django.shortcuts import get_object_or_404
from django.contrib.auth.decorators import login_required
+from django.contrib.auth.models import User
from django.http import HttpResponseRedirect, HttpResponse, HttpResponseForbidden, Http404
from django.utils import simplejson
from django.utils.html import strip_tags, escape
@@ -218,8 +219,10 @@ def ask(request):#view used to ask a new question
ask_anonymously = form.cleaned_data['ask_anonymously']
if request.user.is_authenticated():
+
+ user = form.get_post_user(request.user)
try:
- question = request.user.post_question(
+ question = user.post_question(
title = title,
body_text = text,
tags = tagnames,
@@ -376,7 +379,9 @@ def edit_question(request, id):
is_anon_edit = form.cleaned_data['stay_anonymous']
is_wiki = form.cleaned_data.get('wiki', question.wiki)
- request.user.edit_question(
+ user = form.get_post_user(request.user)
+
+ user.edit_question(
question = question,
title = form.cleaned_data['title'],
body_text = form.cleaned_data['text'],
@@ -446,7 +451,8 @@ def edit_answer(request, id):
if form.is_valid():
if form.has_changed():
- request.user.edit_answer(
+ user = form.get_post_user(request.user)
+ user.edit_answer(
answer = answer,
body_text = form.cleaned_data['text'],
revision_comment = form.cleaned_data['summary'],
@@ -492,7 +498,10 @@ def answer(request, id):#process a new answer
if request.user.is_authenticated():
try:
follow = form.cleaned_data['email_notify']
- answer = request.user.post_answer(
+
+ user = form.get_post_user(request.user)
+
+ answer = user.post_answer(
question = question,
body_text = text,
follow = follow,