diff options
-rw-r--r-- | MANIFEST.in | 1 | ||||
-rw-r--r-- | askbot/conf/__init__.py | 1 | ||||
-rw-r--r-- | askbot/conf/external_keys.py | 49 | ||||
-rw-r--r-- | askbot/conf/spam_and_moderation.py | 32 | ||||
-rw-r--r-- | askbot/const/__init__.py | 63 | ||||
-rw-r--r-- | askbot/context.py | 4 | ||||
-rw-r--r-- | askbot/doc/source/changelog.rst | 1 | ||||
-rw-r--r-- | askbot/locale/en/LC_MESSAGES/django.po | 2 | ||||
-rw-r--r-- | askbot/skins/default/media/jquery-openid/jquery.openid.js | 15 | ||||
-rw-r--r-- | askbot/skins/default/templates/authopenid/providers_javascript.html | 7 | ||||
-rw-r--r-- | askbot/skins/default/templates/blocks/bottom_scripts.html | 2 | ||||
-rw-r--r-- | askbot/skins/default/templates/macros.html | 4 | ||||
-rw-r--r-- | askbot/startup_procedures.py | 1 | ||||
-rw-r--r-- | askbot/utils/decorators.py | 68 | ||||
-rw-r--r-- | askbot/utils/functions.py | 24 | ||||
-rw-r--r-- | askbot/views/writers.py | 22 | ||||
-rw-r--r-- | askbot_requirements.txt | 1 | ||||
-rw-r--r-- | setup.py | 1 |
18 files changed, 223 insertions, 75 deletions
diff --git a/MANIFEST.in b/MANIFEST.in index 484f6b67..7d503fb7 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -4,6 +4,7 @@ include LICENSE include AUTHORS include COPYING include README.rst +include askbot_requirements.txt recursive-include askbot * recursive-exclude askbot *.pyc recursive-exclude .git diff --git a/askbot/conf/__init__.py b/askbot/conf/__init__.py index d51be698..1d2d7240 100644 --- a/askbot/conf/__init__.py +++ b/askbot/conf/__init__.py @@ -13,6 +13,7 @@ import askbot.conf.skin_general_settings import askbot.conf.sidebar_main import askbot.conf.sidebar_question import askbot.conf.sidebar_profile +import askbot.conf.spam_and_moderation import askbot.conf.user_settings import askbot.conf.markup import askbot.conf.social_sharing diff --git a/askbot/conf/external_keys.py b/askbot/conf/external_keys.py index 15ad2903..8912b0ff 100644 --- a/askbot/conf/external_keys.py +++ b/askbot/conf/external_keys.py @@ -1,6 +1,5 @@ -""" -External service key settings -""" +"""External service key settings""" +from askbot import const from askbot.conf.settings_wrapper import settings from askbot.deps import livesettings from django.utils.translation import ugettext as _ @@ -8,7 +7,8 @@ from django.conf import settings as django_settings EXTERNAL_KEYS = livesettings.ConfigurationGroup( 'EXTERNAL_KEYS', - _('Keys to connect the site with external services like Facebook, etc.') + _('Keys to connect the site with external ' + 'services like Facebook, etc.') ) settings.register( @@ -19,11 +19,12 @@ settings.register( help_text=_( 'This key helps google index your site ' 'please obtain is at ' - '<a href="%(google_webmasters_tools_url)s">' + '<a href="%(url)s?hl=%(lang)s">' 'google webmasters tools site</a>' - ) % {'google_webmasters_tools_url': - 'https://www.google.com/webmasters/tools/home?hl=' \ - + django_settings.LANGUAGE_CODE} + ) % { + 'url': const.DEPENDENCY_URLS['google-webmaster-tools'], + 'lang': django_settings.LANGUAGE_CODE, + } ) ) @@ -33,12 +34,12 @@ settings.register( 'GOOGLE_ANALYTICS_KEY', description=_('Google Analytics key'), help_text=_( - 'Obtain is at <a href="%(ga_site)s">' - 'Google Analytics</a> site, if you ' - 'wish to use Google Analytics to monitor ' - 'your site' - ) % {'ga_site':'http://www.google.com/intl/%s/analytics/' \ - % django_settings.LANGUAGE_CODE } + 'Obtain is at <a href="%(url)s">' + 'Google Analytics</a> site, if you ' + 'wish to use Google Analytics to monitor ' + 'your site' + ) % {'url': 'http://www.google.com/intl/%s/analytics/' \ + % django_settings.LANGUAGE_CODE } ) ) @@ -68,8 +69,8 @@ settings.register( 'Recaptcha is a tool that helps distinguish ' 'real people from annoying spam robots. ' 'Please get this and a public key at ' - 'the <a href="http://google.com/recaptcha">http://google.com/recaptcha</a>' - ) + 'the <a href="%(url)s">%(url)s</a>' + ) % {'url': const.DEPENDENCY_URLS['recaptcha']} ) ) @@ -82,9 +83,9 @@ settings.register( 'Facebook API key and Facebook secret ' 'allow to use Facebook Connect login method ' 'at your site. Please obtain these keys ' - 'at <a href="http://www.facebook.com/developers/createapp.php">' + 'at <a href="%(url)s">' 'facebook create app</a> site' - ) + ) % {'url': const.DEPENDENCY_URLS['facebook-apps']} ) ) @@ -102,9 +103,9 @@ settings.register( 'TWITTER_KEY', description=_('Twitter consumer key'), help_text=_( - 'Please register your forum at <a href="http://dev.twitter.com/apps/">' + 'Please register your forum at <a href="%(url)s">' 'twitter applications site</a>' - ), + ) % {'url': const.DEPENDENCY_URLS['twitter-apps']}, ) ) @@ -123,9 +124,9 @@ settings.register( 'LINKEDIN_KEY', description=_('LinkedIn consumer key'), help_text=_( - 'Please register your forum at <a href="https://www.linkedin.com/secure/developer">' + 'Please register your forum at <a href="%(url)s">' 'LinkedIn developer site</a>' - ), + ) % {'url': const.DEPENDENCY_URLS['linkedin-apps']}, ) ) @@ -144,9 +145,9 @@ settings.register( 'IDENTICA_KEY', description=_('ident.ca consumer key'), help_text=_( - 'Please register your forum at <a href="http://identi.ca/settings/oauthapps">' + 'Please register your forum at <a href="%(url)s">' 'Identi.ca applications site</a>' - ), + ) % {'url': const.DEPENDENCY_URLS['identica-apps']}, ) ) diff --git a/askbot/conf/spam_and_moderation.py b/askbot/conf/spam_and_moderation.py new file mode 100644 index 00000000..375fbdd5 --- /dev/null +++ b/askbot/conf/spam_and_moderation.py @@ -0,0 +1,32 @@ +"""Settings for content moderation and spam control""" +from django.utils.translation import ugettext as _ +from askbot import const +from askbot.deps import livesettings +from askbot.conf.settings_wrapper import settings + +SPAM_AND_MODERATION = livesettings.ConfigurationGroup( + 'SPAM_AND_MODERATION', + _('Spam control and content moderation') + ) + +settings.register( + livesettings.BooleanValue( + SPAM_AND_MODERATION, + 'USE_AKISMET', + description=_('Enable Akismet spam detection(keys below are required)'), + default=False, + help_text = _( + 'To get an Akismet key please visit ' + '<a href="%(url)s">Akismet site</a>' + ) % {'url': const.DEPENDENCY_URLS['akismet']} + ) +) + +settings.register( + livesettings.StringValue( + SPAM_AND_MODERATION, + 'AKISMET_API_KEY', + description=_('Akismet key for spam detection') + ) +) + diff --git a/askbot/const/__init__.py b/askbot/const/__init__.py index e62dd2cb..73c71800 100644 --- a/askbot/const/__init__.py +++ b/askbot/const/__init__.py @@ -1,10 +1,11 @@ # encoding:utf-8 -from django.utils.translation import ugettext as _ -import re """ All constants could be used in other modules -For reasons that models, views can't have unicode text in this project, all unicode text go here. +For reasons that models, views can't have unicode +text in this project, all unicode text go here. """ +from django.utils.translation import ugettext as _ +import re CLOSE_REASONS = ( (1, _('duplicate question')), (2, _('question is off-topic or not relevant')), @@ -48,7 +49,8 @@ POST_SORT_METHODS = ( ('relevance-desc', _('relevance')), ) #todo: add assertion here that all sort methods are unique -#because they are keys to the hash used in implementations of Q.run_advanced_search +#because they are keys to the hash used in implementations +#of Q.run_advanced_search DEFAULT_POST_SORT_METHOD = 'activity-desc' POST_SCOPE_LIST = ( @@ -91,28 +93,28 @@ TAG_REGEX = r'^[%s]+$' % TAG_CHARS TAG_SPLIT_REGEX = r'[ ,]+' EMAIL_REGEX = re.compile(r'\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b', re.I) -TYPE_ACTIVITY_ASK_QUESTION=1 -TYPE_ACTIVITY_ANSWER=2 -TYPE_ACTIVITY_COMMENT_QUESTION=3 -TYPE_ACTIVITY_COMMENT_ANSWER=4 -TYPE_ACTIVITY_UPDATE_QUESTION=5 -TYPE_ACTIVITY_UPDATE_ANSWER=6 -TYPE_ACTIVITY_PRIZE=7 -TYPE_ACTIVITY_MARK_ANSWER=8 -TYPE_ACTIVITY_VOTE_UP=9 -TYPE_ACTIVITY_VOTE_DOWN=10 -TYPE_ACTIVITY_CANCEL_VOTE=11 -TYPE_ACTIVITY_DELETE_QUESTION=12 -TYPE_ACTIVITY_DELETE_ANSWER=13 -TYPE_ACTIVITY_MARK_OFFENSIVE=14 -TYPE_ACTIVITY_UPDATE_TAGS=15 -TYPE_ACTIVITY_FAVORITE=16 +TYPE_ACTIVITY_ASK_QUESTION = 1 +TYPE_ACTIVITY_ANSWER = 2 +TYPE_ACTIVITY_COMMENT_QUESTION = 3 +TYPE_ACTIVITY_COMMENT_ANSWER = 4 +TYPE_ACTIVITY_UPDATE_QUESTION = 5 +TYPE_ACTIVITY_UPDATE_ANSWER = 6 +TYPE_ACTIVITY_PRIZE = 7 +TYPE_ACTIVITY_MARK_ANSWER = 8 +TYPE_ACTIVITY_VOTE_UP = 9 +TYPE_ACTIVITY_VOTE_DOWN = 10 +TYPE_ACTIVITY_CANCEL_VOTE = 11 +TYPE_ACTIVITY_DELETE_QUESTION = 12 +TYPE_ACTIVITY_DELETE_ANSWER = 13 +TYPE_ACTIVITY_MARK_OFFENSIVE = 14 +TYPE_ACTIVITY_UPDATE_TAGS = 15 +TYPE_ACTIVITY_FAVORITE = 16 TYPE_ACTIVITY_USER_FULL_UPDATED = 17 TYPE_ACTIVITY_EMAIL_UPDATE_SENT = 18 TYPE_ACTIVITY_MENTION = 19 TYPE_ACTIVITY_UNANSWERED_REMINDER_SENT = 20 -#TYPE_ACTIVITY_EDIT_QUESTION=17 -#TYPE_ACTIVITY_EDIT_ANSWER=18 +#TYPE_ACTIVITY_EDIT_QUESTION = 17 +#TYPE_ACTIVITY_EDIT_ANSWER = 18 #todo: rename this to TYPE_ACTIVITY_CHOICES TYPE_ACTIVITY = ( @@ -250,11 +252,22 @@ DEFAULT_USER_STATUS = 'w' #number of items to show in user views USER_VIEW_DATA_SIZE = 50 +#not really dependency, but external links, which it would +#be nice to test for correctness from time to time DEPENDENCY_URLS = { - 'mathjax': 'http://www.mathjax.org/resources/docs/?installation.html', + 'akismet': 'https://akismet.com/signup/', + 'cc-by-sa': 'http://creativecommons.org/licenses/by-sa/3.0/legalcode', + 'embedding-video': \ + 'http://askbot.org/doc/optional-modules.html#embedding-video', 'favicon': 'http://en.wikipedia.org/wiki/Favicon', - 'embedding-video': 'http://askbot.org/doc/optional-modules.html#embedding-video', - 'cc-by-sa': 'http://creativecommons.org/licenses/by-sa/3.0/legalcode' + 'facebook-apps': 'http://www.facebook.com/developers/createapp.php', + 'google-webmaster-tools': 'https://www.google.com/webmasters/tools/home', + 'identica-apps': 'http://identi.ca/settings/oauthapps', + 'noscript': 'https://www.google.com/support/bin/answer.py?answer=23852', + 'linkedin-apps': 'https://www.linkedin.com/secure/developer', + 'mathjax': 'http://www.mathjax.org/resources/docs/?installation.html', + 'recaptcha': 'http://google.com/recaptcha', + 'twitter-apps': 'http://dev.twitter.com/apps/', } PASSWORD_MIN_LENGTH = 8 diff --git a/askbot/context.py b/askbot/context.py index 5a174585..6dc38f79 100644 --- a/askbot/context.py +++ b/askbot/context.py @@ -5,6 +5,7 @@ and the application available for the templates from django.conf import settings import askbot from askbot import api +from askbot import const from askbot.conf import settings as askbot_settings from askbot.skins.loaders import get_skin from askbot.utils import url_utils @@ -22,5 +23,6 @@ def application_settings(request): return { 'settings': my_settings, 'skin': get_skin(request), - 'moderation_items': api.get_info_on_moderation_items(request.user) + 'moderation_items': api.get_info_on_moderation_items(request.user), + 'noscript_url': const.DEPENDENCY_URLS['noscript'], } diff --git a/askbot/doc/source/changelog.rst b/askbot/doc/source/changelog.rst index ade7421c..c1eaa158 100644 --- a/askbot/doc/source/changelog.rst +++ b/askbot/doc/source/changelog.rst @@ -3,6 +3,7 @@ Changes in Askbot Development version ------------------- +* Added support for Akismet spam detection service (Adolfo Fitoria) * Added noscript message (Arun SAG) * Support for url shortening with TinyUrl on link sharing (Rtnpro) * Allowed logging in with password and email in the place of login name (Evgeny) diff --git a/askbot/locale/en/LC_MESSAGES/django.po b/askbot/locale/en/LC_MESSAGES/django.po index 5bb75eca..a1548a93 100644 --- a/askbot/locale/en/LC_MESSAGES/django.po +++ b/askbot/locale/en/LC_MESSAGES/django.po @@ -499,7 +499,7 @@ msgstr "" #: conf/email.py:22 msgid "Prefix for the email subject line" -msgstr "Welcome to the Q&A forum" +msgstr "" #: conf/email.py:24 msgid "" diff --git a/askbot/skins/default/media/jquery-openid/jquery.openid.js b/askbot/skins/default/media/jquery-openid/jquery.openid.js index 4af89369..7ba9adce 100644 --- a/askbot/skins/default/media/jquery-openid/jquery.openid.js +++ b/askbot/skins/default/media/jquery-openid/jquery.openid.js @@ -298,9 +298,21 @@ $.fn.authenticator = function() { }; var start_password_login_or_change = function(){ + //called upon clicking on one of the password login buttons reset_form(); set_provider_name($(this)); var provider_name = $(this).attr('name'); + return setup_password_login_or_change(provider_name); + }; + + var init_always_visible_password_login = function(){ + reset_form(); + //will break wordpress and ldap + provider_name_input.val('local'); + setup_password_login_or_change('local'); + }; + + var setup_password_login_or_change = function(provider_name){ var token_name = extra_token_name[provider_name] var password_action_input = $('input[name=password_action]'); if (userIsAuthenticated === true){ @@ -427,6 +439,9 @@ $.fn.authenticator = function() { }; setup_default_handlers(); + if (askbot['settings']['signin_always_show_local_login'] === true){ + init_always_visible_password_login(); + } clear_password_fields(); return this; }; diff --git a/askbot/skins/default/templates/authopenid/providers_javascript.html b/askbot/skins/default/templates/authopenid/providers_javascript.html index 85e55e9f..0fe72eb3 100644 --- a/askbot/skins/default/templates/authopenid/providers_javascript.html +++ b/askbot/skins/default/templates/authopenid/providers_javascript.html @@ -34,13 +34,8 @@ {% else %} var userIsAuthenticated = false; {% endif %} - $("body").authenticator(); - {% if settings.SIGNIN_ALWAYS_SHOW_LOCAL_LOGIN %} - {% if settings.SIGNIN_LOCAL_ENABLED %} - $('input.password').remove(); - {% endif %} - {%endif%} askbot['settings']['signin_always_show_local_login'] = {% if settings.SIGNIN_ALWAYS_SHOW_LOCAL_LOGIN %}true{% else %}false{% endif %}; + $("body").authenticator(); </script> {% if settings.FACEBOOK_KEY and settings.FACEBOOK_SECRET %} <div id="fb-root"></div> diff --git a/askbot/skins/default/templates/blocks/bottom_scripts.html b/askbot/skins/default/templates/blocks/bottom_scripts.html index 6fbd6adc..771c13a4 100644 --- a/askbot/skins/default/templates/blocks/bottom_scripts.html +++ b/askbot/skins/default/templates/blocks/bottom_scripts.html @@ -4,7 +4,7 @@ #} <div id="no-javascript"> <noscript class="noscript"> - {% trans app_name = settings.APP_SHORT_NAME %}Please note: {{app_name}} requires javascript to work properly, please enable javascript in your browser{% endtrans %} + {% trans app_name = settings.APP_SHORT_NAME %}Please note: {{app_name}} requires javascript to work properly, please enable javascript in your browser, <a href="{{noscript_url}}">here is how</a>{% endtrans %} </noscript> </div> <script type="text/javascript"> diff --git a/askbot/skins/default/templates/macros.html b/askbot/skins/default/templates/macros.html index 36ab9692..7ddbd70f 100644 --- a/askbot/skins/default/templates/macros.html +++ b/askbot/skins/default/templates/macros.html @@ -138,8 +138,7 @@ {%- macro paginator(p, position='left') -%}{# p is paginator context dictionary #} {% spaceless %} {% if p.is_paginated %} - <div class="paginator"> - <div style="float:{{position}}"> + <div class="paginator" style="float:{{position}}"> {% if p.has_previous %} <span class="prev"><a href="{{p.base_url}}page={{ p.previous }}{{ p.extend_url }}" title="{% trans %}previous{% endtrans %}"> « {% trans %}previous{% endtrans %}</a></span> @@ -169,7 +168,6 @@ <span class="next"><a href="{{p.base_url}}page={{ p.next }}{{ p.extend_url }}" title="{% trans %}next page{% endtrans %}">{% trans %}next page{% endtrans %} »</a></span> {% endif %} </div> - </div> {% endif %} {% endspaceless %} {%- endmacro -%} diff --git a/askbot/startup_procedures.py b/askbot/startup_procedures.py index 4fb41eb6..cc7f86c0 100644 --- a/askbot/startup_procedures.py +++ b/askbot/startup_procedures.py @@ -136,6 +136,7 @@ def try_import(module_name, pypi_package_name): def test_modules(): """tests presence of required modules""" + try_import('akismet', 'akismet') try_import('recaptcha_works', 'django-recaptcha-works') def test_postgres(): diff --git a/askbot/utils/decorators.py b/askbot/utils/decorators.py index f2c86cd5..29e92645 100644 --- a/askbot/utils/decorators.py +++ b/askbot/utils/decorators.py @@ -7,14 +7,17 @@ import inspect import logging from django.conf import settings from django.core import exceptions as django_exceptions -from django.core import urlresolvers +from django.core.urlresolvers import reverse +from django.core.exceptions import ImproperlyConfigured from django.http import HttpResponse, HttpResponseForbidden, Http404 from django.http import HttpResponseRedirect from django.utils import simplejson from django.utils.translation import ugettext as _ +from django.utils.encoding import smart_str from askbot import exceptions as askbot_exceptions from askbot.conf import settings as askbot_settings from askbot.utils import url_utils +from askbot import get_version def auto_now_timestamp(func): """decorator that will automatically set @@ -33,12 +36,12 @@ def auto_now_timestamp(func): def ajax_login_required(view_func): @functools.wraps(view_func) - def wrap(request,*args,**kwargs): + def wrap(request, *args, **kwargs): if request.user.is_authenticated(): - return view_func(request,*args,**kwargs) + return view_func(request, *args, **kwargs) else: json = simplejson.dumps({'login_required':True}) - return HttpResponseForbidden(json,mimetype='application/json') + return HttpResponseForbidden(json, mimetype='application/json') return wrap @@ -74,14 +77,13 @@ def post_only(view_func): return view_func(request, *args, **kwargs) return wrapper - def ajax_only(view_func): @functools.wraps(view_func) - def wrapper(request,*args,**kwargs): + def wrapper(request, *args, **kwargs): if not request.is_ajax(): raise Http404 try: - data = view_func(request,*args,**kwargs) + data = view_func(request, *args, **kwargs) except Exception, e: message = unicode(e) if message == '': @@ -99,7 +101,7 @@ def ajax_only(view_func): else: data['success'] = 1 json = simplejson.dumps(data) - return HttpResponse(json,mimetype='application/json') + return HttpResponse(json, mimetype='application/json') return wrapper def check_authorization_to_post(func_or_message): @@ -166,3 +168,53 @@ def profile(log_file): return _inner return _outer + +def check_spam(field): + '''Decorator to check if there is spam in the form''' + + def decorator(view_func): + @functools.wraps(view_func) + def wrapper(request, *args, **kwargs): + + if askbot_settings.USE_AKISMET and askbot_settings.AKISMET_API_KEY == "": + raise ImproperlyConfigured('You have not set AKISMET_API_KEY') + + if askbot_settings.USE_AKISMET and request.method == "POST": + comment = smart_str(request.POST[field]) + data = {'user_ip': request.META["REMOTE_ADDR"], + 'user_agent': request.environ['HTTP_USER_AGENT'], + 'comment_author': smart_str(request.user.username), + } + if request.user.is_authenticated(): + data.update({'comment_author_email': request.user.email}) + + from akismet import Akismet + api = Akismet( + askbot_settings.AKISMET_API_KEY, + smart_str(askbot_settings.APP_URL), + "Askbot/%s" % get_version() + ) + + if api.comment_check(comment, data, build_data=False): + logging.debug( + 'Spam detected in %s post at: %s', + request.user.username, + datetime.datetime.now() + ) + spam_message = _( + 'Spam was detected on your post, sorry ' + 'for if this is a mistake' + ) + if request.is_ajax(): + return HttpResponseForbidden( + spam_message, + mimetype="application/json" + ) + else: + request.user.message_set.create(message=spam_message) + return HttpResponseRedirect(reverse('index')) + + return view_func(request, *args, **kwargs) + return wrapper + + return decorator diff --git a/askbot/utils/functions.py b/askbot/utils/functions.py index a56ed897..d31d9027 100644 --- a/askbot/utils/functions.py +++ b/askbot/utils/functions.py @@ -2,12 +2,13 @@ import re import datetime from django.utils.translation import ugettext as _ from django.utils.translation import ungettext +from django.contrib.auth.models import User def get_from_dict_or_object(source, key): try: return source[key] except: - return getattr(source,key) + return getattr(source, key) def is_iterable(thing): @@ -53,7 +54,7 @@ def not_a_robot_request(request): return False -def diff_date(date, limen=2, use_on_prefix = False): +def diff_date(date, use_on_prefix = False): now = datetime.datetime.now()#datetime(*time.localtime()[0:6])#??? diff = now - date days = diff.days @@ -74,9 +75,17 @@ def diff_date(date, limen=2, use_on_prefix = False): elif days == 1: return _('yesterday') elif minutes >= 60: - return ungettext('%(hr)d hour ago','%(hr)d hours ago',hours) % {'hr':hours} + return ungettext( + '%(hr)d hour ago', + '%(hr)d hours ago', + hours + ) % {'hr':hours} else: - return ungettext('%(min)d min ago','%(min)d mins ago',minutes) % {'min':minutes} + return ungettext( + '%(min)d min ago', + '%(min)d mins ago', + minutes + ) % {'min':minutes} #todo: this function may need to be removed to simplify the paginator functionality LEADING_PAGE_RANGE_DISPLAYED = TRAILING_PAGE_RANGE_DISPLAYED = 5 @@ -126,3 +135,10 @@ def setup_paginator(context): "pages_outside_trailing_range": pages_outside_trailing_range, "extend_url" : extend_url } + +def get_admin(): + '''Returns an admin users, usefull for raising flags''' + try: + return User.objects.filter(is_superuser=True)[0] + except: + raise Exception('there is no admin users') diff --git a/askbot/views/writers.py b/askbot/views/writers.py index a2540a90..fcc98761 100644 --- a/askbot/views/writers.py +++ b/askbot/views/writers.py @@ -189,6 +189,7 @@ def import_data(request): #@login_required #actually you can post anonymously, but then must register @csrf.csrf_protect @decorators.check_authorization_to_post(_('Please log in to ask questions')) +@decorators.check_spam('text') def ask(request):#view used to ask a new question """a view to ask a new question gives space for q title, body, tags and checkbox for to post as wiki @@ -240,6 +241,18 @@ def ask(request):#view used to ask a new question ) question.save() return HttpResponseRedirect(url_utils.get_login_url()) + else: + form = forms.AskForm(request.POST) + if 'title' in request.GET: + #normally this title is inherited from search query + #but it is possible to ask with a parameter title in the url query + form.initial['title'] = request.GET['title'] + else: + #attempt to extract title from previous search query + search_state = request.session.get('search_state', None) + if search_state: + query = search_state.query + form.initial['title'] = query else: #this branch is for the initial load of ask form form = forms.AskForm() @@ -249,7 +262,7 @@ def ask(request):#view used to ask a new question form.initial['title'] = request.GET['title'] else: #attempt to extract title from previous search query - search_state = request.session.get('search_state',None) + search_state = request.session.get('search_state', None) if search_state: query = search_state.query form.initial['title'] = query @@ -319,6 +332,7 @@ def retag_question(request, id): @login_required @csrf.csrf_protect +@decorators.check_spam('text') def edit_question(request, id): """edit question view """ @@ -406,6 +420,7 @@ def edit_question(request, id): @login_required @csrf.csrf_protect +@decorators.check_spam('text') def edit_answer(request, id): answer = get_object_or_404(models.Answer, id=id) try: @@ -464,6 +479,7 @@ def edit_answer(request, id): #todo: rename this function to post_new_answer @decorators.check_authorization_to_post(_('Please log in to answer questions')) +@decorators.check_spam('text') def answer(request, id):#process a new answer """view that posts new answer @@ -548,6 +564,7 @@ def __generate_comments_json(obj, user):#non-view generates json data for the po data = simplejson.dumps(json_comments) return HttpResponse(data, mimetype="application/json") +@decorators.check_spam('comment') def post_comments(request):#generic ajax handler to load comments to an object # only support get post comments by ajax now user = request.user @@ -587,6 +604,7 @@ def post_comments(request):#generic ajax handler to load comments to an object raise Http404 @decorators.ajax_only +@decorators.check_spam('text') def edit_comment(request): if request.user.is_authenticated(): comment_id = int(request.POST['comment_id']) @@ -609,7 +627,7 @@ def edit_comment(request): 'user_id': comment.user.id, 'is_deletable': is_deletable, 'is_editable': is_editable, - 'score': comment.score, + 'score': comment.score, 'voted': comment.is_upvoted_by(request.user), } else: diff --git a/askbot_requirements.txt b/askbot_requirements.txt index b4b5a1f4..fc11d9d1 100644 --- a/askbot_requirements.txt +++ b/askbot_requirements.txt @@ -1,3 +1,4 @@ +akismet django>=1.1.2 Jinja2 Coffin>=0.3 @@ -7,6 +7,7 @@ import sys #you might want to install django-debug-toolbar as well install_requires = [ + 'akismet', 'django>=1.1.2', 'Jinja2', 'Coffin>=0.3', |