From a16d90151874954a8824c1b9495392f599b70705 Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Sun, 5 Jun 2011 02:11:45 -0400 Subject: almost finished support of other login apps to be used with askbot --- askbot/conf/forum_data_rules.py | 19 +++++- askbot/context.py | 4 ++ askbot/deps/django_authopenid/urls.py | 2 - askbot/deps/django_authopenid/views.py | 6 +- askbot/doc/source/askbot-as-django-application.rst | 41 ++++++++++++ askbot/doc/source/index.rst | 1 + .../commands/add_missing_subscriptions.py | 2 +- .../management/commands/post_emailed_questions.py | 3 +- askbot/management/commands/send_email_alerts.py | 2 +- askbot/models/__init__.py | 76 +++++++++++++--------- .../default/templates/authopenid/complete.html | 2 +- .../skins/default/templates/authopenid/signin.html | 2 +- .../templates/authopenid/signup_with_password.html | 4 +- .../default/templates/blocks/bottom_scripts.html | 2 +- .../templates/blocks/header_meta_links.html | 4 +- askbot/skins/default/templates/faq.html | 2 +- askbot/skins/default/templates/question.html | 4 +- .../default/templates/user_profile/user_info.html | 2 +- askbot/tests/email_alert_tests.py | 4 +- askbot/tests/page_load_tests.py | 1 - askbot/urls.py | 4 +- askbot/utils/url_utils.py | 32 +++++++++ askbot/views/commands.py | 3 +- askbot/views/writers.py | 9 +-- 24 files changed, 170 insertions(+), 61 deletions(-) create mode 100644 askbot/doc/source/askbot-as-django-application.rst create mode 100644 askbot/utils/url_utils.py diff --git a/askbot/conf/forum_data_rules.py b/askbot/conf/forum_data_rules.py index afbbf027..3392278b 100644 --- a/askbot/conf/forum_data_rules.py +++ b/askbot/conf/forum_data_rules.py @@ -8,7 +8,7 @@ from askbot import const FORUM_DATA_RULES = livesettings.ConfigurationGroup( 'FORUM_DATA_RULES', - _('Settings for askbot data entry and display') + _('Data entry and display') ) settings.register( @@ -46,6 +46,23 @@ settings.register( ) ) +settings.register( + livesettings.BooleanValue( + FORUM_DATA_RULES, + 'ALLOW_POSTING_BEFORE_LOGGING_IN', + default = True, + description = _('Allow posting before logging in'), + help_text = _( + 'Check if you want to allow users start posting questions ' + 'or answers before logging in. ' + 'Enabling this may require adjustments in the ' + 'user login system to check for pending posts ' + 'every time the user logs in. The builtin Askbot login system ' + 'supports this feature.' + ) + ) +) + settings.register( livesettings.IntegerValue( FORUM_DATA_RULES, diff --git a/askbot/context.py b/askbot/context.py index f3419abd..5a174585 100644 --- a/askbot/context.py +++ b/askbot/context.py @@ -7,6 +7,7 @@ import askbot from askbot import api from askbot.conf import settings as askbot_settings from askbot.skins.loaders import get_skin +from askbot.utils import url_utils def application_settings(request): """The context processor function""" @@ -15,6 +16,9 @@ def application_settings(request): my_settings['ASKBOT_URL'] = settings.ASKBOT_URL my_settings['DEBUG'] = settings.DEBUG my_settings['ASKBOT_VERSION'] = askbot.get_version() + my_settings['LOGIN_URL'] = url_utils.get_login_url() + my_settings['LOGOUT_URL'] = url_utils.get_logout_url() + my_settings['LOGOUT_REDIRECT_URL'] = url_utils.get_logout_redirect_url() return { 'settings': my_settings, 'skin': get_skin(request), diff --git a/askbot/deps/django_authopenid/urls.py b/askbot/deps/django_authopenid/urls.py index a533f771..f51939ab 100644 --- a/askbot/deps/django_authopenid/urls.py +++ b/askbot/deps/django_authopenid/urls.py @@ -7,8 +7,6 @@ urlpatterns = patterns('askbot.deps.django_authopenid.views', url(r'^yadis.xrdf$', 'xrdf', name='yadis_xrdf'), # manage account registration url(r'^%s$' % _('signin/'), 'signin', name='user_signin'), - url(r'^%s%s$' % (_('signin/'),_('newquestion/')), 'signin', kwargs = {'newquestion':True}, name='user_signin_new_question'), - url(r'^%s%s$' % (_('signin/'),_('newanswer/')), 'signin', kwargs = {'newanswer':True}, name='user_signin_new_answer'), url(r'^%s$' % _('signout/'), 'signout', name='user_signout'), #this view is "complete-openid" signin url(r'^%s%s$' % (_('signin/'), _('complete/')), 'complete_signin', diff --git a/askbot/deps/django_authopenid/views.py b/askbot/deps/django_authopenid/views.py index f43c2dbe..787d7e53 100644 --- a/askbot/deps/django_authopenid/views.py +++ b/askbot/deps/django_authopenid/views.py @@ -267,11 +267,7 @@ def complete_oauth_signin(request): #@not_authenticated @csrf.csrf_protect -def signin( - request, - newquestion = False,#todo: not needed - newanswer = False,#todo: not needed - ): +def signin(request): """ signin page. It manages the legacy authentification (user/password) and openid authentification diff --git a/askbot/doc/source/askbot-as-django-application.rst b/askbot/doc/source/askbot-as-django-application.rst new file mode 100644 index 00000000..09c0a81e --- /dev/null +++ b/askbot/doc/source/askbot-as-django-application.rst @@ -0,0 +1,41 @@ +===================================== +Askbot as reusable django application +===================================== + +Askbot can be used both as as dedicated site and as an application +within a larger site. There are still issues to resolve to make askbot +a truly reusable app, but some are already solved. + +This page is a guide for using askbot as an independent app and it is +somewhat technical. + +Using alternative login system +============================== + +Askbot has a bundled application for user login and registration, +but it can be replaced with any other. + +There are two caveats. If you want the "allow posting before logging in" feature +(which can be enabled/disabled at +"settings"->"data entry and display"->"allow posting before logging in"), +you must either insure that your app calls ``user.post_anonymous_askbot_content()`` +right after the user logs in, or activate middleware +``askbot.middleware.anon_posts.PublishAnonPostsMiddleware``. + +The middleware solution is not desirable, as it will cause additional +database queries each time a logged in user loads any page on the site. + +Second thing to keep in mind is in askbot each user has records for +email subscription settings, and these will be missing when user +registers via some alternative login application. This is not a big problem +and should not lead to errors, however some users may miss email notifications +until their records complete. + +The email subscription settings complete automatically when certain pages +are visited, but there is a way to accelerate this process by calling +management command:: + + python manage.py add_missing_subscriptions + +Alternatively, you can insert the following call just after the new user +account is created ``user.add_missing_askbot_subscriptions()`` diff --git a/askbot/doc/source/index.rst b/askbot/doc/source/index.rst index fedc3913..5ab51397 100644 --- a/askbot/doc/source/index.rst +++ b/askbot/doc/source/index.rst @@ -23,6 +23,7 @@ at the forum_ or by email at admin@askbot.org Appendix A: Maintenance procedures Appendix B: Sending email to askbot Appendix C: Optional modules + Appendix D: Askbot as Django application Footnotes Contributors diff --git a/askbot/management/commands/add_missing_subscriptions.py b/askbot/management/commands/add_missing_subscriptions.py index b30822d1..70b1590e 100644 --- a/askbot/management/commands/add_missing_subscriptions.py +++ b/askbot/management/commands/add_missing_subscriptions.py @@ -8,5 +8,5 @@ class Command(NoArgsCommand): @transaction.commit_manually def handle_noargs(self, **options): for user in User.object.all(): - user.add_missing_subscriptions() + user.add_missing_askbot_subscriptions() transaction.commit() diff --git a/askbot/management/commands/post_emailed_questions.py b/askbot/management/commands/post_emailed_questions.py index 73b5ed3e..0a038b62 100644 --- a/askbot/management/commands/post_emailed_questions.py +++ b/askbot/management/commands/post_emailed_questions.py @@ -27,6 +27,7 @@ from django.utils.translation import string_concat from django.core.urlresolvers import reverse from askbot.conf import settings as askbot_settings from askbot.utils import mail +from askbot.utils import url_utils from askbot import models from askbot.forms import AskByEmailForm @@ -61,7 +62,7 @@ def bounce_email(email, subject, reason = None, body_text = None): 'by email, please register first

' ) % { 'site': askbot_settings.APP_SHORT_NAME, - 'url': askbot_settings.APP_URL + reverse('user_signin') + 'url': url_utils.get_login_url() } elif reason == 'permission_denied': error_message = _( diff --git a/askbot/management/commands/send_email_alerts.py b/askbot/management/commands/send_email_alerts.py index 53a5db46..f92aff63 100644 --- a/askbot/management/commands/send_email_alerts.py +++ b/askbot/management/commands/send_email_alerts.py @@ -388,7 +388,7 @@ class Command(NoArgsCommand): #does not change the database, only sends the email #todo: move this to template for user in User.objects.all(): - user.add_missing_subscriptions() + user.add_missing_askbot_subscriptions() #todo: q_list is a dictionary, not a list q_list = self.get_updated_questions_for_user(user) if len(q_list.keys()) == 0: diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py index e4a1280e..3afcefef 100644 --- a/askbot/models/__init__.py +++ b/askbot/models/__init__.py @@ -861,6 +861,37 @@ def user_post_comment( ) return comment +def user_post_anonymous_askbot_content(user, session_key): + """posts any posts added just before logging in + the posts are identified by the session key, thus the second argument + + this function is used by the signal handler with a similar name + """ + aq_list = AnonymousQuestion.objects.filter(session_key = session_key) + aa_list = AnonymousAnswer.objects.filter(session_key = session_key) + #from askbot.conf import settings as askbot_settings + if askbot_settings.EMAIL_VALIDATION == True:#add user to the record + for aq in aq_list: + aq.author = user + aq.save() + for aa in aa_list: + aa.author = user + aa.save() + #maybe add pending posts message? + else: + if user.is_blocked(): + msg = _('blocked users cannot post') + user.message_set.create(message = msg) + elif user.is_suspended(): + msg = _('suspended users cannot post') + user.message_set.create(message = msg) + else: + for aq in aq_list: + aq.publish(user) + for aa in aa_list: + aa.publish(user) + + def user_mark_tags( self, tagnames = None, @@ -1320,7 +1351,7 @@ def user_set_admin_status(self): self.is_staff = True self.is_superuser = True -def user_add_missing_subscriptions(self): +def user_add_missing_askbot_subscriptions(self): from askbot import forms#need to avoid circular dependency form = forms.EditUserEmailFeedsForm() need_feed_types = form.get_db_model_subscription_type_names() @@ -1865,7 +1896,10 @@ def user_update_wildcard_tag_selections( return new_tags -User.add_to_class('add_missing_subscriptions', user_add_missing_subscriptions) +User.add_to_class( + 'add_missing_askbot_subscriptions', + user_add_missing_askbot_subscriptions +) User.add_to_class('is_username_taken',classmethod(user_is_username_taken)) User.add_to_class( 'get_followed_question_alert_frequency', @@ -1885,6 +1919,10 @@ User.add_to_class('edit_question', user_edit_question) User.add_to_class('retag_question', user_retag_question) User.add_to_class('post_answer', user_post_answer) User.add_to_class('edit_answer', user_edit_answer) +User.add_to_class( + 'post_anonymous_askbot_content', + user_post_anonymous_askbot_content +) User.add_to_class('post_comment', user_post_comment) User.add_to_class('edit_comment', user_edit_comment) User.add_to_class('delete_post', user_delete_post) @@ -2384,7 +2422,7 @@ def complete_pending_tag_subscriptions(sender, request, *args, **kwargs): message = _('Your tag subscription was saved, thanks!') ) -def post_stored_anonymous_content( +def post_anonymous_askbot_content( sender, request, user, @@ -2392,30 +2430,10 @@ def post_stored_anonymous_content( signal, *args, **kwargs): - - aq_list = AnonymousQuestion.objects.filter(session_key = session_key) - aa_list = AnonymousAnswer.objects.filter(session_key = session_key) - #from askbot.conf import settings as askbot_settings - if askbot_settings.EMAIL_VALIDATION == True:#add user to the record - for aq in aq_list: - aq.author = user - aq.save() - for aa in aa_list: - aa.author = user - aa.save() - #maybe add pending posts message? - else: - if user.is_blocked(): - msg = _('blocked users cannot post') - user.message_set.create(message = msg) - elif user.is_suspended(): - msg = _('suspended users cannot post') - user.message_set.create(message = msg) - else: - for aq in aq_list: - aq.publish(user) - for aa in aa_list: - aa.publish(user) + """signal handler, unfortunately extra parameters + are necessary for the signal machinery, even though + they are not used in this function""" + user.post_anonymous_askbot_content(session_key) def set_user_has_custom_avatar_flag(instance, created, **kwargs): instance.user.update_has_custom_avatar() @@ -2453,8 +2471,8 @@ signals.flag_offensive.connect(record_flag_offensive, sender=Question) signals.flag_offensive.connect(record_flag_offensive, sender=Answer) signals.tags_updated.connect(record_update_tags) signals.user_updated.connect(record_user_full_updated, sender=User) -signals.user_logged_in.connect(post_stored_anonymous_content) -signals.user_logged_in.connect(complete_pending_tag_subscriptions) +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) signals.post_updated.connect( record_post_update_activity, sender=Comment diff --git a/askbot/skins/default/templates/authopenid/complete.html b/askbot/skins/default/templates/authopenid/complete.html index 40ec4ccc..969a173f 100644 --- a/askbot/skins/default/templates/authopenid/complete.html +++ b/askbot/skins/default/templates/authopenid/complete.html @@ -52,7 +52,7 @@ parameters: {% elif login_type=='facebook' %}
{% csrf_token %} {% else %} - {% csrf_token %} + {% csrf_token %} {% endif %} {{ openid_register_form.next }}
diff --git a/askbot/skins/default/templates/authopenid/signin.html b/askbot/skins/default/templates/authopenid/signin.html index 4cbd905a..5cff194b 100644 --- a/askbot/skins/default/templates/authopenid/signin.html +++ b/askbot/skins/default/templates/authopenid/signin.html @@ -46,7 +46,7 @@

{{ openid_error_message }}

{% endif %} {% if view_subtype != 'email_sent' and view_subtype != 'bad_key' %} - {% csrf_token %} + {% csrf_token %} {# in this branch - the real signin view we display the login icons here we hide the local login button only if admin wants to always show the password login form - then diff --git a/askbot/skins/default/templates/authopenid/signup_with_password.html b/askbot/skins/default/templates/authopenid/signup_with_password.html index b5680806..047ff076 100644 --- a/askbot/skins/default/templates/authopenid/signup_with_password.html +++ b/askbot/skins/default/templates/authopenid/signup_with_password.html @@ -8,7 +8,7 @@ {% block content %} {% if settings.PASSWORD_REGISTER_SHOW_PROVIDER_BUTTONS == True %}

{% trans %}Please register by clicking on any of the icons below{% endtrans %}

- {% csrf_token %} + {% csrf_token %} {# hide_local_login == True because it is password reg form #} {{ login_macros.provider_buttons( @@ -47,7 +47,7 @@
{% if settings.PASSWORD_REGISTER_SHOW_PROVIDER_BUTTONS == False %} {% trans %}or{% endtrans %} - {% trans %}return to OpenID login{% endtrans %} + {% trans %}return to OpenID login{% endtrans %} {% endif %}
diff --git a/askbot/skins/default/templates/blocks/bottom_scripts.html b/askbot/skins/default/templates/blocks/bottom_scripts.html index b5b88bce..aaad70c0 100644 --- a/askbot/skins/default/templates/blocks/bottom_scripts.html +++ b/askbot/skins/default/templates/blocks/bottom_scripts.html @@ -22,7 +22,7 @@ askbot['urls']['get_tag_list'] = '{% url "get_tag_list" %}'; askbot['urls']['follow_user'] = scriptUrl + 'followit/follow/user/{{'{{'}}userId{{'}}'}}/'; askbot['urls']['unfollow_user'] = scriptUrl + 'followit/unfollow/user/{{'{{'}}userId{{'}}'}}/'; - askbot['urls']['user_signin'] = '{% url "user_signin" %}'; + askbot['urls']['user_signin'] = '{{ settings.LOGIN_URL }}';