diff options
author | Benjamin ABEL <bbig26@gmail.com> | 2014-06-13 10:27:54 +0200 |
---|---|---|
committer | Benjamin ABEL <bbig26@gmail.com> | 2014-06-13 10:27:54 +0200 |
commit | b0c7b45addb99c04166b81e4b64e06051e674d48 (patch) | |
tree | e055de63dc3d5dc2f9d20554a3cfc118348da064 | |
parent | e5e67d4d549f162931a233b8c3358c294e375c80 (diff) | |
parent | e1fc221ed540ad7b36bdf6e0f6a306898b4b2249 (diff) | |
download | askbot-b0c7b45addb99c04166b81e4b64e06051e674d48.tar.gz askbot-b0c7b45addb99c04166b81e4b64e06051e674d48.tar.bz2 askbot-b0c7b45addb99c04166b81e4b64e06051e674d48.zip |
Merge branch 'master' of github.com:ASKBOT/askbot-devel
46 files changed, 261 insertions, 193 deletions
diff --git a/askbot/conf/external_keys.py b/askbot/conf/external_keys.py index 3837b7ae..989cbf46 100644 --- a/askbot/conf/external_keys.py +++ b/askbot/conf/external_keys.py @@ -53,8 +53,6 @@ settings.register( ) ) - - settings.register( livesettings.StringValue( EXTERNAL_KEYS, diff --git a/askbot/conf/login_providers.py b/askbot/conf/login_providers.py index 3c30bffa..beb56a72 100644 --- a/askbot/conf/login_providers.py +++ b/askbot/conf/login_providers.py @@ -23,6 +23,8 @@ settings.register( ) ) +#todo: remove this - we don't want the local login button +#but instead always show the login/password field when used settings.register( livesettings.BooleanValue( LOGIN_PROVIDERS, diff --git a/askbot/conf/minimum_reputation.py b/askbot/conf/minimum_reputation.py index 58b41c18..d0db5891 100644 --- a/askbot/conf/minimum_reputation.py +++ b/askbot/conf/minimum_reputation.py @@ -17,6 +17,16 @@ MIN_REP = livesettings.ConfigurationGroup( settings.register( livesettings.IntegerValue( MIN_REP, + 'MIN_REP_TO_AUTOAPPROVE_USER', + default=10, + description=_('Become approved'), + help_text=_('Approved users bypass moderation and skip recaptcha') + ) +) + +settings.register( + livesettings.IntegerValue( + MIN_REP, 'MIN_REP_TO_VOTE_UP', default=5, description=_('Upvote') diff --git a/askbot/deps/django_authopenid/forms.py b/askbot/deps/django_authopenid/forms.py index 5f64ccd5..9e069ed8 100644 --- a/askbot/deps/django_authopenid/forms.py +++ b/askbot/deps/django_authopenid/forms.py @@ -39,7 +39,7 @@ from django.conf import settings as django_settings from askbot.conf import settings as askbot_settings from askbot import const as askbot_const from django.utils.safestring import mark_safe -from recaptcha_works.fields import RecaptchaField +from askbot.forms import AskbotRecaptchaField from askbot.utils.forms import NextUrlField, UserNameField, UserEmailField, SetPasswordForm from askbot.utils.loading import load_module @@ -55,7 +55,6 @@ __all__ = [ 'OpenidSigninForm','OpenidRegisterForm', 'ClassicRegisterForm', 'ChangePasswordForm', 'ChangeEmailForm', 'EmailPasswordForm', 'DeleteForm', - 'ChangeOpenidForm' ] class LoginProviderField(forms.CharField): @@ -321,6 +320,14 @@ class OpenidRegisterForm(forms.Form): username = UserNameField(widget_attrs={'tabindex': 0}) email = UserEmailField() +class SafeOpenidRegisterForm(OpenidRegisterForm): + """this form uses recaptcha in addition + to the base register form + """ + def __init__(self, *args, **kwargs): + super(SafeOpenidRegisterForm, self).__init__(*args, **kwargs) + self.fields['recaptcha'] = AskbotRecaptchaField() + class ClassicRegisterForm(SetPasswordForm): """ legacy registration form """ @@ -334,10 +341,9 @@ class SafeClassicRegisterForm(ClassicRegisterForm): """this form uses recaptcha in addition to the base register form """ - recaptcha = RecaptchaField( - private_key = askbot_settings.RECAPTCHA_SECRET, - public_key = askbot_settings.RECAPTCHA_KEY - ) + def __init__(self, *args, **kwargs): + super(SafeClassicRegisterForm, self).__init__(*args, **kwargs) + self.fields['recaptcha'] = AskbotRecaptchaField() class ChangePasswordForm(forms.Form): """ change password form """ @@ -486,5 +492,7 @@ def get_registration_form_class(): custom_class = getattr(django_settings, 'REGISTRATION_FORM', None) if custom_class: return load_module(custom_class) + elif askbot_settings.USE_RECAPTCHA: + return SafeOpenidRegisterForm else: return OpenidRegisterForm diff --git a/askbot/deps/django_authopenid/views.py b/askbot/deps/django_authopenid/views.py index 4ac42733..ac106777 100644 --- a/askbot/deps/django_authopenid/views.py +++ b/askbot/deps/django_authopenid/views.py @@ -996,6 +996,7 @@ def finalize_generic_signin( @not_authenticated @csrf.csrf_protect +@fix_recaptcha_remote_ip def register(request, login_provider_name=None, user_identifier=None): """ this function is used via it's own url with request.method=POST diff --git a/askbot/forms.py b/askbot/forms.py index e4e927eb..e218f381 100644 --- a/askbot/forms.py +++ b/askbot/forms.py @@ -24,6 +24,10 @@ from askbot.conf import get_tag_display_filter_strategy_choices from tinymce.widgets import TinyMCE import logging +def should_use_recaptcha(user): + """True if user must use recaptcha""" + return askbot_settings.USE_RECAPTCHA and (user.is_anonymous() or user.is_watched()) + def cleanup_dict(dictionary, key, empty_value): """deletes key from dictionary if it exists @@ -210,6 +214,14 @@ class CountedWordsField(forms.CharField): return value +class AskbotRecaptchaField(RecaptchaField): + """A recaptcha field with preset keys from the livesettings""" + def __init__(self, *args, **kwargs): + kwargs.setdefault('private_key', askbot_settings.RECAPTCHA_SECRET) + kwargs.setdefault('public_key', askbot_settings.RECAPTCHA_KEY) + super(AskbotRecaptchaField, self).__init__(*args, **kwargs) + + class LanguageField(forms.ChoiceField): def __init__(self, *args, **kwargs): @@ -721,13 +733,6 @@ class SendMessageForm(forms.Form): ) -class NotARobotForm(forms.Form): - recaptcha = RecaptchaField( - private_key=askbot_settings.RECAPTCHA_SECRET, - public_key=askbot_settings.RECAPTCHA_KEY - ) - - class FeedbackForm(forms.Form): name = forms.CharField(label=_('Your name (optional):'), required=False) email = forms.EmailField(label=_('Email:'), required=False) @@ -741,18 +746,12 @@ class FeedbackForm(forms.Form): ) next = NextUrlField() - def __init__(self, is_auth=False, *args, **kwargs): + def __init__(self, user=None, *args, **kwargs): super(FeedbackForm, self).__init__(*args, **kwargs) - self.is_auth = is_auth - if not is_auth: - if askbot_settings.USE_RECAPTCHA: - self._add_recaptcha_field() - - def _add_recaptcha_field(self): - self.fields['recaptcha'] = RecaptchaField( - private_key=askbot_settings.RECAPTCHA_SECRET, - public_key=askbot_settings.RECAPTCHA_KEY - ) + self.user = user + if should_use_recaptcha(user): + self.fields['recaptcha'] = AskbotRecaptchaField() + def clean_message(self): message = self.cleaned_data.get('message', '').strip() if not message: @@ -761,7 +760,7 @@ class FeedbackForm(forms.Form): def clean(self): super(FeedbackForm, self).clean() - if not self.is_auth: + if self.user and self.user.is_anonymous(): if not self.cleaned_data['no_email'] \ and not self.cleaned_data['email']: msg = _('Please mark "I dont want to give my mail" field.') @@ -942,6 +941,9 @@ class AskForm(PostAsSomeoneForm, PostPrivatelyForm): if askbot_settings.ALLOW_ASK_ANONYMOUSLY is False: self.hide_field('ask_anonymously') + if should_use_recaptcha(user): + self.fields['recaptcha'] = AskbotRecaptchaField() + def clean_ask_anonymously(self): """returns false if anonymous asking is not allowed """ @@ -978,6 +980,9 @@ class AskWidgetForm(forms.Form, FormWithHideableFields): self.fields['text'].required = False self.fields['text'].min_length = 0 + if should_use_recaptcha(user): + self.fields['recaptcha'] = AskbotRecaptchaField() + class CreateAskWidgetForm(forms.Form, FormWithHideableFields): title = forms.CharField(max_length=100) include_text_field = forms.BooleanField(required=False) @@ -1121,7 +1126,11 @@ class AnswerForm(PostAsSomeoneForm, PostPrivatelyForm): def __init__(self, *args, **kwargs): super(AnswerForm, self).__init__(*args, **kwargs) - self.fields['text'] = AnswerEditorField(user=kwargs['user']) + user = kwargs['user'] + self.fields['text'] = AnswerEditorField(user=user) + + if should_use_recaptcha(user): + self.fields['recaptcha'] = AskbotRecaptchaField() def has_data(self): """True if form is bound or has inital data""" @@ -1237,6 +1246,9 @@ class EditQuestionForm(PostAsSomeoneForm, PostPrivatelyForm): if getattr(django_settings, 'ASKBOT_MULTILINGUAL', False): self.fields['language'] = LanguageField() + if should_use_recaptcha(self.user): + self.fields['recaptcha'] = AskbotRecaptchaField() + def has_changed(self): if super(EditQuestionForm, self).has_changed(): return True @@ -1344,6 +1356,9 @@ class EditAnswerForm(PostAsSomeoneForm, PostPrivatelyForm): self.fields['text'].initial = revision.text self.fields['wiki'].initial = answer.wiki + if should_use_recaptcha(user): + self.fields['recaptcha'] = AskbotRecaptchaField() + def has_changed(self): #todo: this function is almost copy/paste of EditQuestionForm.has_changed() if super(EditAnswerForm, self).has_changed(): diff --git a/askbot/importers/stackexchange/management/commands/load_stackexchange.py b/askbot/importers/stackexchange/management/commands/load_stackexchange.py index ff6ddb15..902bc988 100644 --- a/askbot/importers/stackexchange/management/commands/load_stackexchange.py +++ b/askbot/importers/stackexchange/management/commands/load_stackexchange.py @@ -915,7 +915,7 @@ it may be helpful to split this procedure in two:\n u = askbot.User() u_type = se_u.user_type.name if u_type == 'Administrator': - u.set_admin_status() + u.set_status('d') elif u_type == 'Moderator': u.set_status('m') elif u_type not in ('Unregistered', 'Registered'): diff --git a/askbot/management/commands/add_admin.py b/askbot/management/commands/add_admin.py index 6f7c7034..3f8f7fea 100644 --- a/askbot/management/commands/add_admin.py +++ b/askbot/management/commands/add_admin.py @@ -41,5 +41,4 @@ class Command(NoArgsCommand): self.confirm_action() self.remove_signals() - self.user.set_admin_status() - self.user.save() + self.user.set_status('d') diff --git a/askbot/management/commands/createsuperuser.py b/askbot/management/commands/createsuperuser.py index eb363bbd..d0faf253 100644 --- a/askbot/management/commands/createsuperuser.py +++ b/askbot/management/commands/createsuperuser.py @@ -100,8 +100,7 @@ class Command(Command): self.remove_signals() u = User.objects.create_superuser(username, email, password) - u.set_admin_status() - u.save() + u.set_status('d') if verbosity >= 1: self.stdout.write("Askbot Superuser created successfully.\n") diff --git a/askbot/management/commands/remove_admin.py b/askbot/management/commands/remove_admin.py index 2aa95c20..eca0b7b6 100644 --- a/askbot/management/commands/remove_admin.py +++ b/askbot/management/commands/remove_admin.py @@ -41,5 +41,4 @@ class Command(NoArgsCommand): self.confirm_action() self.remove_signals() - self.user.remove_admin_status() - self.user.save() + self.user.set_status('a') diff --git a/askbot/management/commands/send_email_alerts.py b/askbot/management/commands/send_email_alerts.py index dbaff93f..1f04690f 100644 --- a/askbot/management/commands/send_email_alerts.py +++ b/askbot/management/commands/send_email_alerts.py @@ -480,7 +480,7 @@ class Command(NoArgsCommand): 'name': user.username, 'admin_email': askbot_settings.ADMIN_EMAIL, 'site_name': askbot_settings.APP_SHORT_NAME, - 'is_multilingual': django_settings.ASKBOT_MULTILINGUAL + 'is_multilingual': getattr(django_settings, 'ASKBOT_MULTILINGUAL', False) }) if DEBUG_THIS_COMMAND == True: diff --git a/askbot/media/jquery-openid/jquery.openid.js b/askbot/media/jquery-openid/jquery.openid.js index 520f031c..dac4d297 100644 --- a/askbot/media/jquery-openid/jquery.openid.js +++ b/askbot/media/jquery-openid/jquery.openid.js @@ -74,7 +74,7 @@ $.fn.authenticator = function() { if (confirm(message)){ $.ajax({ type: 'POST', - url: authUrl + 'delete_login_method/',//url!!! + url: askbot['urls']['deleteLoginMethod'], data: {provider_name: provider_name}, success: function(data, text_status, xhr){ $(provider_row).remove(); diff --git a/askbot/media/js/group_messaging.js b/askbot/media/js/group_messaging.js index add50425..58572e2d 100644 --- a/askbot/media/js/group_messaging.js +++ b/askbot/media/js/group_messaging.js @@ -674,10 +674,10 @@ MessageCenter.prototype.hitThreadsList = function(url, senderId, requestMethod) me.setThreadsList(threads); me.setState('show-list'); me.setLoadingStatus(false); - }, + } + }, error: function() { me.setLoadingStatus(false); - } } }); this.setLoadingStatus(true); diff --git a/askbot/media/style/style.css b/askbot/media/style/style.css index e1787790..d86b8fc7 100644 --- a/askbot/media/style/style.css +++ b/askbot/media/style/style.css @@ -330,6 +330,9 @@ body.user-messages { background: white; display: block; } +.select-language { + margin-top: 6px; +} #userToolsNav { /* Navigation bar containing login link or user information, check widgets/user_navigation.html*/ @@ -3005,19 +3008,26 @@ a:hover.medal { border: #eee 1px solid; padding: 5px; } +.user-profile-page form { + margin-bottom: 0; +} .user-profile-page h2 { - padding: 30px 0px 10px 0px; + padding: 4px 0px 10px 0px; font-family: 'Open Sans Condensed', Arial, sans-serif; } +.user-profile-page h3 { + padding: 0; + margin-top: -3px; +} +.user-profile-page .submit-row { + margin-bottom: 0; +} .user-profile-page .user-stats-table h2 { padding-top: 10px; } .user-profile-page .user-stats-table.badges { margin-bottom: 30px; } -.user-profile-page select { - margin-bottom: 12px; -} .user-profile-page .up-votes, .user-profile-page .down-votes { display: inline-block; @@ -3048,6 +3058,18 @@ a:hover.medal { .user-profile-page .users-questions { margin-top: -10px; } +.user-profile-page .avatar p { + margin-bottom: 0px; +} +.user-profile-page .tabBar a#stats { + margin-left: 0; +} +.user-profile-page img.gravatar { + margin: 2px 0 3px 0; +} +.user-profile-page .vote-notification h3 { + padding: 10px; +} .user-details { font-size: 13px; } @@ -3872,25 +3894,6 @@ p.signup_p { .avatar-page li { display: inline; } -.user-profile-page .avatar p { - margin-bottom: 0px; -} -.user-profile-page .tabBar a#stats { - margin-left: 0; -} -.user-profile-page img.gravatar { - margin: 2px 0 3px 0; -} -.user-profile-page h3 { - padding: 0; - margin-top: -3px; -} -.user-profile-page .vote-notification h3 { - padding: 10px; -} -.user-profile-page ul.tags { - margin-left: 5px; -} .userList { font-size: 13px; } @@ -4360,6 +4363,10 @@ td.setting-input textarea { -o-transition: border linear 0.2s, box-shadow linear 0.2s; transition: border linear 0.2s, box-shadow linear 0.2s; } +#recaptcha_area, +#recaptcha_table { + line-height: 0!important; +} .acInput { width: 200px; } diff --git a/askbot/media/style/style.less b/askbot/media/style/style.less index 748591df..09b2810f 100644 --- a/askbot/media/style/style.less +++ b/askbot/media/style/style.less @@ -338,6 +338,9 @@ body.user-messages { display: block; } } +.select-language { + margin-top: 6px; +} #userToolsNav {/* Navigation bar containing login link or user information, check widgets/user_navigation.html*/ height: 20px; @@ -2938,13 +2941,13 @@ ul#related-tags li { .users-page, .user-profile-edit-page, .user-profile-page { - form{ + form { margin-bottom:15px; } input[type="text"], input[type="password"], - select{ + select { height:25px; line-height: 25px; padding-left:5px; @@ -3136,7 +3139,7 @@ a:hover.medal { /* profile page */ -.tabBar-profile{ +.tabBar-profile { width:100%; margin-bottom:5px; float:left; @@ -3145,7 +3148,7 @@ a:hover.medal { .user-profile-page { color:@info-text-dark; - p{ + p { font-size:13px; line-height:1.3; color:@info-text-dark; @@ -3155,11 +3158,24 @@ a:hover.medal { padding:5px; } + form { + margin-bottom: 0; + } + h2 { - padding: 30px 0px 10px 0px; + padding: 4px 0px 10px 0px; font-family: @main-font; } + h3 { + padding: 0; + margin-top: -3px; + } + + .submit-row { + margin-bottom: 0; + } + .user-stats-table h2 { padding-top: 10px; } @@ -3168,9 +3184,6 @@ a:hover.medal { margin-bottom: 30px; } - select { - margin-bottom: 12px; - } .up-votes, .down-votes { display: inline-block; @@ -3181,9 +3194,11 @@ a:hover.medal { line-height: 22px; margin: 0 15px 0 2px; } + .up-votes { background: url(../images/vote-arrow-up-on.png) no-repeat; } + .down-votes { background: url(../images/vote-arrow-down-on.png) no-repeat; } @@ -3202,6 +3217,19 @@ a:hover.medal { .users-questions { margin-top: -10px; } + + .avatar p { + margin-bottom: 0px; + } + .tabBar a#stats { + margin-left: 0; + } + img.gravatar { + margin: 2px 0 3px 0; + } + .vote-notification h3 { + padding: 10px; + } } .user-details { @@ -4134,28 +4162,6 @@ p.signup_p { display: inline; } -.user-profile-page { - .avatar p { - margin-bottom: 0px; - } - .tabBar a#stats { - margin-left: 0; - } - img.gravatar { - margin: 2px 0 3px 0; - } - h3 { - padding: 0; - margin-top: -3px; - } - .vote-notification h3 { - padding: 10px; - } - ul.tags { - margin-left: 5px; - } -} - .userList { font-size: 13px; } @@ -4574,6 +4580,10 @@ td.setting-input { } } +#recaptcha_area, #recaptcha_table { + line-height: 0!important; +} + .acInput { width: 200px; } diff --git a/askbot/middleware/remote_ip.py b/askbot/middleware/remote_ip.py new file mode 100644 index 00000000..18280d0d --- /dev/null +++ b/askbot/middleware/remote_ip.py @@ -0,0 +1,21 @@ +"""Fixes REMOTE_IP meta value +based on the HTTP_X_FORWARDED_FOR value, if used. +Enable this middleware if using django site behind a proxy +server or a load balancer. + +Add to the MIDDLEWARE_CLASSES: + + 'askbot.middleware.remote_ip.SetRemoteIPFromXForwardedFor', +""" + +class SetRemoteIPFromXForwardedFor(object): + def process_request(self, request): + try: + real_ip = request.META['HTTP_X_FORWARDED_FOR'] + except KeyError: + pass + else: + # HTTP_X_FORWARDED_FOR can be a comma-separated list of IPs. + # Take just the first one. + real_ip = real_ip.split(",")[0] + request.META['REMOTE_ADDR'] = real_ip diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py index 5dace35c..b2bebd76 100644 --- a/askbot/models/__init__.py +++ b/askbot/models/__init__.py @@ -99,8 +99,7 @@ def get_admin(): if User.objects.filter(username='_admin_').count() == 0: admin = User.objects.create_user('_admin_', '') admin.set_unusable_password() - admin.set_admin_status() - admin.save() + admin.set_status('d') return admin else: raise User.DoesNotExist @@ -308,11 +307,10 @@ def user_get_avatar_url(self, size=48): raise django_exceptions.ImproperlyConfigured(message) else: return self.get_gravatar_url(size) + if askbot_settings.ENABLE_GRAVATAR: + return self.get_gravatar_url(size) else: - if askbot_settings.ENABLE_GRAVATAR: - return self.get_gravatar_url(size) - else: - return self.get_default_avatar_url(size) + return self.get_default_avatar_url(size) def user_get_top_answers_paginator(self, visitor=None): """get paginator for top answers by the user for a @@ -357,6 +355,9 @@ def user_strip_email_signature(self, text): return text def _check_gravatar(gravatar): + return 'n' + #todo: think of whether we need this and if so + #how to check the avatar type appropriately gravatar_url = askbot_settings.GRAVATAR_BASE_URL + "/%s?d=404" % gravatar code = urllib.urlopen(gravatar_url).getcode() if urllib.urlopen(gravatar_url).getcode() != 404: @@ -2745,11 +2746,13 @@ def user_update_response_counts(user): def user_receive_reputation(self, num_points): - new_points = self.reputation + num_points + old_points = self.reputation + new_points = old_points + num_points if new_points > 0: self.reputation = new_points else: self.reputation = const.MIN_REPUTATION + signals.reputation_received.send(None, user=self, reputation_before=old_points) def user_update_wildcard_tag_selections( self, @@ -3681,8 +3684,7 @@ def make_admin_if_first_user(user, **kwargs): import sys user_count = User.objects.all().count() if user_count == 1: - user.set_admin_status() - user.save() + user.set_status('d') def moderate_group_joining(sender, instance=None, created=False, **kwargs): if created and instance.level == GroupMembership.PENDING: @@ -3700,6 +3702,13 @@ def tweet_new_post(sender, user=None, question=None, answer=None, form_data=None post = question or answer tweet_new_post_task.delay(post.id) +def autoapprove_reputable_user(user=None, reputation_before=None, *args, **kwargs): + """if user is 'watched' we change status to 'approved' + if user's rep crossed the auto-approval margin""" + margin = askbot_settings.MIN_REP_TO_AUTOAPPROVE_USER + if user.is_watched() and reputation_before < margin and user.reputation >= margin: + user.set_status('a') + def init_badge_data(sender, created_models=None, **kwargs): if BadgeData in created_models: from askbot.models import badges @@ -3722,7 +3731,7 @@ django_signals.post_save.connect(moderate_group_joining, sender=GroupMembership) if 'avatar' in django_settings.INSTALLED_APPS: from avatar.models import Avatar - django_signals.post_save.connect(set_user_avatar_type_flag,sender=Avatar) + django_signals.post_save.connect(set_user_avatar_type_flag, sender=Avatar) django_signals.post_delete.connect(update_user_avatar_type_flag, sender=Avatar) django_signals.post_delete.connect(record_cancel_vote, sender=Vote) @@ -3740,6 +3749,7 @@ signals.user_logged_in.connect(post_anonymous_askbot_content) signals.post_updated.connect(record_post_update_activity) signals.new_answer_posted.connect(tweet_new_post) signals.new_question_posted.connect(tweet_new_post) +signals.reputation_received.connect(autoapprove_reputable_user) #probably we cannot use post-save here the point of this is #to tell when the revision becomes publicly visible, not when it is saved diff --git a/askbot/models/signals.py b/askbot/models/signals.py index 42a9c787..00152a0a 100644 --- a/askbot/models/signals.py +++ b/askbot/models/signals.py @@ -52,6 +52,7 @@ post_revision_published = django.dispatch.Signal( ] ) site_visited = django.dispatch.Signal(providing_args=['user', 'timestamp']) +reputation_received = django.dispatch.Signal(providing_args=['user', 'reputation_before']) def pop_signal_receivers(signal): """disables a given signal by removing listener functions diff --git a/askbot/schedules.py b/askbot/schedules.py deleted file mode 100644 index b9bbdbc8..00000000 --- a/askbot/schedules.py +++ /dev/null @@ -1,19 +0,0 @@ -"""tests on whether certain scheduled tasks need -to be performed at the moment""" -from datetime import datetime - -def should_update_avatar_data(request): - """True if it is time to update user's avatar data - user is taken from the request object - """ - user = request.user - if user.is_authenticated(): - if (datetime.today() - user.last_login).days <= 1: - #avatar is updated on login anyway - return False - updated_at = request.session.get('avatar_data_updated_at', None) - if updated_at is None: - return True - else: - return (datetime.now() - updated_at).days > 0 - return False diff --git a/askbot/templates/answer_edit.html b/askbot/templates/answer_edit.html index c9d8a147..5ba0881b 100644 --- a/askbot/templates/answer_edit.html +++ b/askbot/templates/answer_edit.html @@ -21,6 +21,10 @@ editor_type = settings.EDITOR_TYPE ) }} + {% if form.recaptcha %} + <div>{{ macros.form_field_with_errors(form.recaptcha) }}</div> + <div class="clearfix"></div> + {% endif %} <div class="answer-options"> {% if settings.WIKI_ON and answer.wiki == False %} {{ macros.checkbox_in_div(form.wiki) }} diff --git a/askbot/templates/authopenid/complete.html b/askbot/templates/authopenid/complete.html index c41f0a0f..cefb1941 100644 --- a/askbot/templates/authopenid/complete.html +++ b/askbot/templates/authopenid/complete.html @@ -63,11 +63,15 @@ anyone, must be valid</i>) {% endif %} {{ openid_register_form.email }} </div> + {% if openid_register_form.recaptcha %} + <div class="form-row-vertical"> + {{ macros.form_field_with_errors(openid_register_form.recaptcha ) }} + </div> + {% endif %} <div class="submit-row"> <input id="register-button" type="submit" - class="submit" name="bnewaccount" value="{% trans %}Signup{% endtrans %}" /> diff --git a/askbot/templates/authopenid/providers_javascript.html b/askbot/templates/authopenid/providers_javascript.html index 668fb1e9..d20f052f 100644 --- a/askbot/templates/authopenid/providers_javascript.html +++ b/askbot/templates/authopenid/providers_javascript.html @@ -5,10 +5,10 @@ <script type="text/javascript" src="{{ "/jquery-openid/jquery.openid.js"|media }}"></script> <script type="text/javascript"> askbot['urls']['changePassword'] = '{% url change_password %}'; + askbot['urls']['deleteLoginMethod'] = '{% url delete_login_method %}'; var extra_token_name = {}; var create_pw_text = {}; var change_pw_text = {}; - var authUrl = '/{% trans %}account/{% endtrans %}'; var siteName = '{{settings.APP_SHORT_NAME}}'; var provider_count = {{existing_login_methods|length}}; {% for login_provider in major_login_providers %} diff --git a/askbot/templates/authopenid/signup_with_password.html b/askbot/templates/authopenid/signup_with_password.html index c3625b62..ef8d8572 100644 --- a/askbot/templates/authopenid/signup_with_password.html +++ b/askbot/templates/authopenid/signup_with_password.html @@ -38,9 +38,8 @@ your login details with anyone and having to remember yet another password.{% en <li><label for="password1_id">{{form.password1.label}}</label>{{form.password1}}{{form.password1.errors}}</li> <li><label for="password2_id">{{form.password2.label}}</label>{{form.password2}}{{form.password2.errors}}</li> </ul> - {% if settings.USE_RECAPTCHA %} - <p class="signup_p">{% trans %}Please read and type in the two words below to help us prevent automated account creation.{% endtrans %}</p> - {{form.recaptcha}} + {% if form.recaptcha %} + {{ main_macros.form_field_with_errors(form.recaptcha) }} {% endif %} <div class="submit-row"><input id="signup-button" type="submit" class="button" value="{% trans %}Signup{% endtrans %}" /> {% if settings.PASSWORD_REGISTER_SHOW_PROVIDER_BUTTONS == False %} diff --git a/askbot/templates/authopenid/verify_email.html b/askbot/templates/authopenid/verify_email.html index 613ca589..1312658b 100644 --- a/askbot/templates/authopenid/verify_email.html +++ b/askbot/templates/authopenid/verify_email.html @@ -8,7 +8,7 @@ </label> <form method="post">{% csrf_token %} <input id="validation-code" type="text" name="validation_code" /> - <input type="submit" class="submit" value="{% trans %}Confirm email{% endtrans %}" /> + <input type="submit" value="{% trans %}Confirm email{% endtrans %}" /> </form> {% endblock %} <!-- end changeemail.html --> diff --git a/askbot/templates/close.html b/askbot/templates/close.html index 70d7cc8b..b0c239e4 100644 --- a/askbot/templates/close.html +++ b/askbot/templates/close.html @@ -12,8 +12,8 @@ {{ form.reason }} </p> <p> - <input type="submit" value="{% trans %}OK to close{% endtrans %}" class="submit" /> - <input id="btBack" type="button" class="submit" value="{% trans %}Cancel{% endtrans %}" /> + <input type="submit" value="{% trans %}OK to close{% endtrans %}"/> + <input id="btBack" type="button" value="{% trans %}Cancel{% endtrans %}"/> </p> </form> {% endblock %} diff --git a/askbot/templates/email/change_settings_info.html b/askbot/templates/email/change_settings_info.html index 55bd729f..0f96caa4 100644 --- a/askbot/templates/email/change_settings_info.html +++ b/askbot/templates/email/change_settings_info.html @@ -5,7 +5,6 @@ {% else %} {% trans %}To change freqency and content of these alerts, please visit <a href="{{ url }}">your user profile</a>.{% endtrans %} {% endif %} -</p> -<p style="font-size:10px; font-style:italic;"> + <br/> {% trans %}If you believe that this message was sent in an error, please email about it the forum administrator at <a href="mailto:{{ admin_email }}">{{ admin_email }}</a>.{% endtrans %} </p> diff --git a/askbot/templates/embed/widget_form.html b/askbot/templates/embed/widget_form.html index ad1562aa..a03aba29 100644 --- a/askbot/templates/embed/widget_form.html +++ b/askbot/templates/embed/widget_form.html @@ -11,7 +11,7 @@ {{ form.as_table() }} <tr> <td colspan="2" style="text-align: center"> - <input type="submit" class="submit" value={% trans %}Save{% endtrans %} /> + <input type="submit" value={% trans %}Save{% endtrans %} /> </td> </tr> </table> diff --git a/askbot/templates/feedback.html b/askbot/templates/feedback.html index 04b9a5b4..040566c6 100644 --- a/askbot/templates/feedback.html +++ b/askbot/templates/feedback.html @@ -1,4 +1,5 @@ {% extends "two_column_body.html" %} +{% import "macros.html" as macros %} <!-- template feedback.html --> {% block title %}{% spaceless %}{% trans %}Feedback{% endtrans %}{% endspaceless %}{% endblock %} {% block content %} @@ -51,17 +52,13 @@ </div> {% if form.recaptcha %} <div class="form-row"> - {% if form.errors.recaptcha%} - <span class="error">{% trans %}(Please solve the captcha){% endtrans %}</span> - </label> - {% endif %} - {{form.recaptcha}} + {{ macros.form_field_with_errors(form.recaptcha) }} </div> {% endif %} {{form.next}} <div class="submit-row"> - <input type="submit" class="submit" value="{% trans %}Send Feedback{% endtrans %}"/> - <input type="submit" class="submit cancel" name="cancel" value="{% trans %}Cancel{% endtrans %}"/> + <input type="submit" value="{% trans %}Send Feedback{% endtrans %}"/> + <input type="submit" class="cancel" name="cancel" value="{% trans %}Cancel{% endtrans %}"/> </div> </form> {% endblock %} diff --git a/askbot/templates/macros.html b/askbot/templates/macros.html index 7ceb4eab..b314255c 100644 --- a/askbot/templates/macros.html +++ b/askbot/templates/macros.html @@ -848,3 +848,10 @@ for the purposes of the AJAX comment editor #} })(); </script> {% endmacro %} + +{% macro form_field_with_errors(field) %} + {% if field.errors %} + <p class="error">{{ field.errors|join(", ") }}</p> + {% endif %} + {{ field }} +{% endmacro %} diff --git a/askbot/templates/main_page/javascript.html b/askbot/templates/main_page/javascript.html index 72d63ed3..3a3c3d23 100644 --- a/askbot/templates/main_page/javascript.html +++ b/askbot/templates/main_page/javascript.html @@ -6,10 +6,6 @@ Hilite.exact = false; Hilite.elementid = "question-list"; Hilite.debug_referrer = location.href; - {% if update_avatar_data == True %} - var today = new Date();{#add timestamp to prevent browser caching #} - $.getJSON('{% url user_update_has_custom_avatar %}?t=' + today.getTime()); - {% endif %} }); askbot['urls']['mark_interesting_tag'] = '{% url mark_interesting_tag %}'; diff --git a/askbot/templates/question/new_answer_form.html b/askbot/templates/question/new_answer_form.html index f8b4cd46..9e8644d4 100644 --- a/askbot/templates/question/new_answer_form.html +++ b/askbot/templates/question/new_answer_form.html @@ -41,6 +41,10 @@ editor_type = settings.EDITOR_TYPE ) }} + {% if answer.recaptcha %} + <div>{{ macros.form_field_with_errors(answer.recaptcha) }}</div> + <div class="clearfix"></div> + {% endif %} <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/templates/question_edit.html b/askbot/templates/question_edit.html index e31050ec..f6de6bdf 100644 --- a/askbot/templates/question_edit.html +++ b/askbot/templates/question_edit.html @@ -35,6 +35,10 @@ ) }} <div class="after-editor"> + {% if form.recaptcha %} + <div>{{ macros.form_field_with_errors(form.recaptcha) }}</div> + <div class="clearfix"></div> + {% endif %} <div class="question-options"> {% if settings.WIKI_ON and question.wiki == False %} {{ macros.checkbox_in_div(form.wiki) }} @@ -58,7 +62,7 @@ </div> {% endif %} </div> - <input id="edit_post_form_submit_button" type="submit" value="{% trans %}Save edit{% endtrans %}" class="large submit" /> + <input id="edit_post_form_submit_button" type="submit" value="{% trans %}Save edit{% endtrans %}" class="large submit" /> <input type="button" value="{% trans %}Cancel{% endtrans %}" class="large submit" onclick="history.back(-1);" /> </div> diff --git a/askbot/templates/question_retag.html b/askbot/templates/question_retag.html index e1341f7a..df8dc584 100644 --- a/askbot/templates/question_retag.html +++ b/askbot/templates/question_retag.html @@ -18,8 +18,8 @@ </div> </div> <div class="error" ></div> - <input type="submit" value="{% trans %}Retag{% endtrans %}" class="submit" /> - <input type="button" value="{% trans %}Cancel{% endtrans %}" class="submit" onclick="history.back(-1);" /> + <input type="submit" value="{% trans %}Retag{% endtrans %}"/> + <input type="button" value="{% trans %}Cancel{% endtrans %}" onclick="history.back(-1);" /> </form> {% endblock %} diff --git a/askbot/templates/reopen.html b/askbot/templates/reopen.html index 9c617403..07208793 100644 --- a/askbot/templates/reopen.html +++ b/askbot/templates/reopen.html @@ -22,8 +22,8 @@ <p>{{ settings.WORDS_REOPEN_QUESTION|escape }}?</p> <form id="fmclose" action="{% url reopen question.id %}" method="post" >{% csrf_token %} <div id="" style="padding:20px 0 20px 0"> - <input type="submit" value="{{ settings.WORDS_REOPEN_QUESTION|escape }}" class="submit" /> - <input id="btBack" type="button" value="{% trans %}Cancel{% endtrans %}" class="submit" /> + <input type="submit" value="{{ settings.WORDS_REOPEN_QUESTION|escape }}"/> + <input id="btBack" type="button" value="{% trans %}Cancel{% endtrans %}"/> </div> </form> {% endblock %} diff --git a/askbot/templates/tags/form_bulk_tag_subscription.html b/askbot/templates/tags/form_bulk_tag_subscription.html index 95168e45..b6e72a96 100644 --- a/askbot/templates/tags/form_bulk_tag_subscription.html +++ b/askbot/templates/tags/form_bulk_tag_subscription.html @@ -9,7 +9,7 @@ <form action="." method="POST" accept-charset="utf-8"> <table border="0"> {{form.as_table()}} -<tr><td/><td><input type="submit" class="submit" value="Save"></td></tr> +<tr><td/><td><input type="submit" value="Save"></td></tr> </table> </form> {% endblock %} diff --git a/askbot/templates/user_profile/user.html b/askbot/templates/user_profile/user.html index 8164784d..1f939d11 100644 --- a/askbot/templates/user_profile/user.html +++ b/askbot/templates/user_profile/user.html @@ -23,7 +23,6 @@ var viewUserID = {{view_user.id}}; askbot['data']['viewUserName'] = '{{ view_user.username|escape }}'; askbot['data']['viewUserId'] = {{ view_user.id }}; - askbot['data']['userPostsPageSize'] = {{ page_size }}; askbot['urls']['edit_group_membership'] = '{% url edit_group_membership %}'; askbot['urls']['getGroupsList'] = '{% url get_groups_list %}'; askbot['urls']['getTopAnswers'] = '{% url get_top_answers %}'; diff --git a/askbot/templates/user_profile/user_edit.html b/askbot/templates/user_profile/user_edit.html index c95bf815..fa9ecfdd 100644 --- a/askbot/templates/user_profile/user_edit.html +++ b/askbot/templates/user_profile/user_edit.html @@ -106,8 +106,8 @@ {% endif %} </table> <div style="margin:30px 0 60px 0"> - <input type="submit" value="{% trans %}Update{% endtrans %}" class="submit" > - <input id="cancel" type="button" value="{% trans %}Cancel{% endtrans %}" class="submit" > + <input type="submit" value="{% trans %}Update{% endtrans %}"/> + <input id="cancel" type="button" value="{% trans %}Cancel{% endtrans %}"/> </div> </div> </form> diff --git a/askbot/templates/user_profile/user_email_subscriptions.html b/askbot/templates/user_profile/user_email_subscriptions.html index fdda03b7..100ce789 100644 --- a/askbot/templates/user_profile/user_email_subscriptions.html +++ b/askbot/templates/user_profile/user_email_subscriptions.html @@ -20,8 +20,8 @@ {{tag_filter_selection_form}} </table> <div class="submit-row text-align-right"> - <input type="submit" class="submit" name="save" value="{% trans %}Update{% endtrans %}"/> - <input type="submit" class="submit" name="stop_email" value="{% trans %}Stop Email{% endtrans %}"/> + <input type="submit" name="save" value="{% trans %}Update{% endtrans %}"/> + <input type="submit" name="stop_email" value="{% trans %}Stop Email{% endtrans %}"/> </div> </form> </div> @@ -53,7 +53,7 @@ css_class = 'subscribed marked-tags special', ) }} - <br/> + <div class="clearfix"></div> <div class="inputs"> <input id="subscribedTagInput" autocomplete="off" type="text"/> <input id="subscribedTagAdd" type="submit" value="{% trans %}add{% endtrans%}"/> @@ -61,14 +61,15 @@ </div> {%endif%} {% endblock %} -{%block userjs%} - <script type='text/javascript'> - search = new FullTextSearch(); - askbot['controllers'] = askbot['controllers'] || {} - askbot['controllers']['fullTextSearch'] = search; - askbot['urls']['mark_subscribed_tag'] = '{% url mark_subscribed_tag %}'; - askbot['urls']['unmark_tag'] = '{% url unmark_tag %}'; - </script> - <script type='text/javascript' src='{{"/js/tag_selector.js"|media}}'></script> +{% block userjs %} + <script type='text/javascript'> + search = new FullTextSearch(); + askbot['controllers'] = askbot['controllers'] || {} + askbot['controllers']['fullTextSearch'] = search; + askbot['urls']['mark_subscribed_tag'] = '{% url mark_subscribed_tag %}'; + askbot['urls']['unmark_tag'] = '{% url unmark_tag %}'; + askbot['settings']['tag_editor'] = '{{ tag_editor_settings|escapejs }}'; + </script> + <script type='text/javascript' src='{{"/js/tag_selector.js"|media}}'></script> {% endblock %} <!-- end user_email_subscriptions.html --> diff --git a/askbot/templates/user_profile/user_moderate.html b/askbot/templates/user_profile/user_moderate.html index a7f05b1c..75c6d6fe 100644 --- a/askbot/templates/user_profile/user_moderate.html +++ b/askbot/templates/user_profile/user_moderate.html @@ -17,7 +17,7 @@ </table> <p id="id_user_status_info"> </p> - <input type="submit" class="submit" name="change_status" value="{% trans %}Save{% endtrans %}" /> + <input type="submit" name="change_status" value="{% trans %}Save{% endtrans %}" /> </form> {% endif %} <h3> @@ -35,8 +35,8 @@ <table class="form-as-table"> {{ change_user_reputation_form.as_table() }} </table> - <input type="submit" class="submit" name="subtract_reputation" value="{% trans %}Subtract{% endtrans %}" /> - <input type="submit" class="submit" name="add_reputation" value="{% trans %}Add{% endtrans %}" /> + <input type="submit" name="subtract_reputation" value="{% trans %}Subtract{% endtrans %}" /> + <input type="submit" name="add_reputation" value="{% trans %}Add{% endtrans %}" /> </form> {% if request.user != view_user %} <hr/> @@ -61,7 +61,7 @@ {% endif %} {{ send_message_form.body_text}} </div> - <input type="submit" class="submit" name="send_message" value="{% trans %}Send message{% endtrans %}" /> + <input type="submit" name="send_message" value="{% trans %}Send message{% endtrans %}" /> </form> {% endif %} {% endblock %} diff --git a/askbot/templates/user_profile/user_stats.html b/askbot/templates/user_profile/user_stats.html index 7bb97d88..344051af 100644 --- a/askbot/templates/user_profile/user_stats.html +++ b/askbot/templates/user_profile/user_stats.html @@ -101,6 +101,7 @@ {% block endjs %} {{ super() }} <script type="text/javascript"> + askbot['data']['userPostsPageSize'] = {{ page_size }}; askbot['urls']['join_or_leave_group'] = '{% url join_or_leave_group %}'; $(document).ready(function(){ setup_badge_details_toggle(); diff --git a/askbot/templates/widgets/ask_form.html b/askbot/templates/widgets/ask_form.html index df37ba3c..6e165857 100644 --- a/askbot/templates/widgets/ask_form.html +++ b/askbot/templates/widgets/ask_form.html @@ -61,6 +61,10 @@ </div> {% endif %} </div> + {% if form.recaptcha %} + <div>{{ macros.form_field_with_errors(form.recaptcha) }}</div> + <div class="clearfix"></div> + {% endif %} {% if not request.user.is_authenticated() %} <input type="submit" name="post_anon" value="{% trans %}Login/Signup to Post{% endtrans %}" class="submit" /> {% else %} diff --git a/askbot/urls.py b/askbot/urls.py index 551fa329..566173ce 100644 --- a/askbot/urls.py +++ b/askbot/urls.py @@ -125,11 +125,6 @@ urlpatterns = patterns('', name='groups' ), url( - r'^%s$' % _('users/update_has_custom_avatar/'), - views.users.update_has_custom_avatar, - name='user_update_has_custom_avatar' - ), - url( r'^%s$' % _('badges/'), views.meta.badges, name='badges' diff --git a/askbot/views/meta.py b/askbot/views/meta.py index 8a91e72a..a27f2971 100644 --- a/askbot/views/meta.py +++ b/askbot/views/meta.py @@ -107,10 +107,7 @@ def feedback(request): return HttpResponseRedirect(redirect_url) if request.method == "POST": - form = FeedbackForm( - is_auth=request.user.is_authenticated(), - data=request.POST - ) + form = FeedbackForm(user=request.user, data=request.POST) if form.is_valid(): if not request.user.is_authenticated(): @@ -145,8 +142,10 @@ def feedback(request): request.user.message_set.create(message=msg) return HttpResponseRedirect(get_next_url(request)) else: - form = FeedbackForm(is_auth = request.user.is_authenticated(), - initial={'next':get_next_url(request)}) + form = FeedbackForm( + user=request.user, + initial={'next':get_next_url(request)} + ) data['form'] = form return render(request, 'feedback.html', data) diff --git a/askbot/views/readers.py b/askbot/views/readers.py index 89f802d1..3c3b053c 100644 --- a/askbot/views/readers.py +++ b/askbot/views/readers.py @@ -42,7 +42,6 @@ from askbot.forms import GetDataForPostForm from askbot.utils.loading import load_module from askbot import conf from askbot import models -from askbot import schedules from askbot.models.tag import Tag from askbot import const from askbot.startup_procedures import domain_is_bad @@ -252,7 +251,6 @@ def questions(request, **kwargs): 'font_size' : extra_tags.get_tag_font_size(related_tags), 'display_tag_filter_strategy_choices': conf.get_tag_display_filter_strategy_choices(), 'email_tag_filter_strategy_choices': conf.get_tag_email_filter_strategy_choices(), - 'update_avatar_data': schedules.should_update_avatar_data(request), 'query_string': search_state.query_string(), 'search_state': search_state, 'feed_url': context_feed_url, diff --git a/askbot/views/users.py b/askbot/views/users.py index 64f0e38e..91f210d9 100644 --- a/askbot/views/users.py +++ b/askbot/views/users.py @@ -998,6 +998,8 @@ def user_email_subscriptions(request, user, context): 'user_languages': user.languages.split() } context.update(data) + #todo: really need only if subscribed tags are enabled + context.update(view_context.get_for_tag_editor()) return render( request, 'user_profile/user_email_subscriptions.html', @@ -1094,17 +1096,6 @@ def user(request, id, slug=None, tab_name=None): context['custom_tab_slug'] = CUSTOM_TAB['SLUG'] return user_view_func(request, profile_owner, context) -@csrf.csrf_exempt -def update_has_custom_avatar(request): - """updates current avatar type data for the user - """ - if request.is_ajax() and request.user.is_authenticated(): - if request.user.avatar_type in ('n', 'g'): - request.user.update_avatar_type() - request.session['avatar_data_updated_at'] = datetime.datetime.now() - return HttpResponse(simplejson.dumps({'status':'ok'}), mimetype='application/json') - return HttpResponseForbidden() - def groups(request, id = None, slug = None): """output groups page """ diff --git a/askbot/views/writers.py b/askbot/views/writers.py index 04103d50..395ba3d8 100644 --- a/askbot/views/writers.py +++ b/askbot/views/writers.py @@ -46,6 +46,7 @@ from askbot.views import context from askbot.templatetags import extra_filters_jinja as template_filters from askbot.importers.stackexchange import management as stackexchange#todo: may change from askbot.utils.slug import slugify +from recaptcha_works.decorators import fix_recaptcha_remote_ip # used in index page INDEX_PAGE_SIZE = 20 @@ -204,6 +205,7 @@ def import_data(request): return render(request, 'import_data.html', data) #@login_required #actually you can post anonymously, but then must register +@fix_recaptcha_remote_ip @csrf.csrf_protect @decorators.check_authorization_to_post(ugettext_lazy('Please log in to make posts')) @decorators.check_spam('text') @@ -223,8 +225,8 @@ def ask(request):#view used to ask a new question if askbot_settings.READ_ONLY_MODE_ENABLED: return HttpResponseRedirect(reverse('index')) - form = forms.AskForm(request.REQUEST, user=request.user) if request.method == 'POST': + form = forms.AskForm(request.POST, user=request.user) if form.is_valid(): timestamp = datetime.datetime.now() title = form.cleaned_data['title'] @@ -383,6 +385,7 @@ def retag_question(request, id): @login_required @csrf.csrf_protect @decorators.check_spam('text') +@fix_recaptcha_remote_ip def edit_question(request, id): """edit question view """ @@ -493,6 +496,7 @@ def edit_question(request, id): @login_required @csrf.csrf_protect @decorators.check_spam('text') +@fix_recaptcha_remote_ip def edit_answer(request, id): answer = get_object_or_404(models.Post, id=id) @@ -588,6 +592,7 @@ def edit_answer(request, id): #todo: rename this function to post_new_answer @decorators.check_authorization_to_post(ugettext_lazy('Please log in to make posts')) @decorators.check_spam('text') +@fix_recaptcha_remote_ip def answer(request, id, form_class=forms.AnswerForm):#process a new answer """view that posts new answer |