diff options
author | Evgeny Fadeev <evgeny.fadeev@gmail.com> | 2014-05-14 01:36:38 -0300 |
---|---|---|
committer | Evgeny Fadeev <evgeny.fadeev@gmail.com> | 2014-05-14 01:36:38 -0300 |
commit | 5ca8a04794d35e2f9b6955a2c45d9a3cc925cd4f (patch) | |
tree | 71641d9648fda88861618d1f02c60e27c020d492 | |
parent | d3f23e60c7137ba5e8aa7d8869099627ff26e4de (diff) | |
parent | 09e39545c5c5cd0319cfdc603e951a5ae42f063f (diff) | |
download | askbot-5ca8a04794d35e2f9b6955a2c45d9a3cc925cd4f.tar.gz askbot-5ca8a04794d35e2f9b6955a2c45d9a3cc925cd4f.tar.bz2 askbot-5ca8a04794d35e2f9b6955a2c45d9a3cc925cd4f.zip |
Merge pull request #217 from keto/protect-convert-views
CSRF protection and user checks for answer and comment converting views
-rw-r--r-- | askbot/media/js/utils.js | 19 | ||||
-rw-r--r-- | askbot/models/__init__.py | 18 | ||||
-rw-r--r-- | askbot/templates/macros.html | 5 | ||||
-rw-r--r-- | askbot/templates/question/answer_comments.html | 3 | ||||
-rw-r--r-- | askbot/templates/question/question_comments.html | 3 | ||||
-rw-r--r-- | askbot/views/writers.py | 17 |
6 files changed, 59 insertions, 6 deletions
diff --git a/askbot/media/js/utils.js b/askbot/media/js/utils.js index 64932ccd..ef4309bd 100644 --- a/askbot/media/js/utils.js +++ b/askbot/media/js/utils.js @@ -277,6 +277,19 @@ var notify = function() { }; }(); +/* + * CSRF token extractor + */ +var getCSRFToken = function() { + var re = /_csrf=([^;]*)/; + var match = re.exec(document.cookie); + if(match) + return match[1]; + else + return '' +} + + /* **************************************************** */ // Search query-string manipulation utils /* **************************************************** */ @@ -1374,6 +1387,12 @@ CommentConvertLink.prototype.createDom = function(){ hidden_input.attr('id', 'id_comment_id'); element.append(hidden_input); + var csrf_token = this.makeElement('input'); + csrf_token.attr('type', 'hidden'); + csrf_token.attr('name', 'csrfmiddlewaretoken'); + csrf_token.attr('value', getCSRFToken()); + element.append(csrf_token); + var submit = this.makeElement('input'); submit.attr('type', 'submit'); submit.attr('value', gettext('convert to answer')); diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py index 4156bb0c..5dace35c 100644 --- a/askbot/models/__init__.py +++ b/askbot/models/__init__.py @@ -837,6 +837,20 @@ def user_assert_can_edit_comment(self, comment = None): ) raise django_exceptions.PermissionDenied(error_message) +def user_assert_can_convert_post(self, post = None): + """raises exceptions.PermissionDenied if user is not allowed to convert the + post to another type (comment -> answer, answer -> comment) + + only owners, moderators or admins can convert posts + """ + if self.is_administrator() or self.is_moderator() or post.author == self: + return + + error_message = _( + 'Sorry, but only post owners or moderators convert posts' + ) + raise django_exceptions.PermissionDenied(error_message) + def user_can_post_comment(self, parent_post = None): """a simplified method to test ability to comment @@ -1385,7 +1399,7 @@ def user_repost_comment_as_answer(self, comment): parent question""" #todo: add assertion - #self.assert_can_repost_comment_as_answer(comment) + self.assert_can_convert_post(comment) comment.post_type = 'answer' old_parent = comment.parent @@ -2998,6 +3012,8 @@ User.add_to_class('assert_can_delete_post', user_assert_can_delete_post) User.add_to_class('assert_can_restore_post', user_assert_can_restore_post) User.add_to_class('assert_can_delete_comment', user_assert_can_delete_comment) User.add_to_class('assert_can_edit_comment', user_assert_can_edit_comment) +User.add_to_class('assert_can_convert_post', user_assert_can_convert_post) + User.add_to_class('assert_can_delete_answer', user_assert_can_delete_answer) User.add_to_class('assert_can_delete_question', user_assert_can_delete_question) User.add_to_class('assert_can_accept_best_answer', user_assert_can_accept_best_answer) diff --git a/askbot/templates/macros.html b/askbot/templates/macros.html index 699bd7f3..7ceb4eab 100644 --- a/askbot/templates/macros.html +++ b/askbot/templates/macros.html @@ -388,7 +388,8 @@ for the purposes of the AJAX comment editor #} show_comment = None, show_comment_position = None, user=None, - max_comments=None + max_comments=None, + csrf_token=None ) -%} {% spaceless %} @@ -451,7 +452,7 @@ for the purposes of the AJAX comment editor #} accept-charset="utf-8" class='convert-comment' > - {% csrf_token %} + <input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}"> <input type="hidden" value="{{comment.id}}" name="comment_id" id="id_comment_id"> <input type="submit" value="{% trans %}convert to answer{% endtrans %}"> </form> diff --git a/askbot/templates/question/answer_comments.html b/askbot/templates/question/answer_comments.html index e6b5e1c5..c0a0dfd8 100644 --- a/askbot/templates/question/answer_comments.html +++ b/askbot/templates/question/answer_comments.html @@ -5,6 +5,7 @@ show_comment = show_comment, show_comment_position = show_comment_position, user = request.user, - max_comments = settings.MAX_COMMENTS_TO_SHOW + max_comments = settings.MAX_COMMENTS_TO_SHOW, + csrf_token = csrf_token ) }} diff --git a/askbot/templates/question/question_comments.html b/askbot/templates/question/question_comments.html index e9d3f724..a05f6328 100644 --- a/askbot/templates/question/question_comments.html +++ b/askbot/templates/question/question_comments.html @@ -5,6 +5,7 @@ show_comment = show_comment, show_comment_position = show_comment_position, user = request.user, - max_comments = settings.MAX_COMMENTS_TO_SHOW + max_comments = settings.MAX_COMMENTS_TO_SHOW, + csrf_token = csrf_token ) }} diff --git a/askbot/views/writers.py b/askbot/views/writers.py index 88e5e0cf..04103d50 100644 --- a/askbot/views/writers.py +++ b/askbot/views/writers.py @@ -852,7 +852,13 @@ def delete_comment(request): @login_required @decorators.post_only +@csrf.csrf_protect def comment_to_answer(request): + if request.user.is_anonymous(): + msg = _('Sorry, only logged in users can convert comments to answers. ' + 'Please <a href="%(sign_in_url)s">sign in</a>.') % \ + {'sign_in_url': url_utils.get_login_url()} + raise exceptions.PermissionDenied(msg) form = forms.ProcessCommentForm(request.POST) if form.is_valid() == False: @@ -879,14 +885,23 @@ def repost_answer_as_comment(request, destination=None): 'comment_under_previous_answer' ) ) + if request.user.is_anonymous(): + msg = _('Sorry, only logged in users can convert answers to comments. ' + 'Please <a href="%(sign_in_url)s">sign in</a>.') % \ + {'sign_in_url': url_utils.get_login_url()} + raise exceptions.PermissionDenied(msg) answer_id = request.POST.get('answer_id') if answer_id: - answer_id = int(answer_id) + try: + answer_id = int(answer_id) + except (ValueError, TypeError): + raise Http404 answer = get_object_or_404(models.Post, post_type = 'answer', id=answer_id) if askbot_settings.READ_ONLY_MODE_ENABLED: return HttpResponseRedirect(answer.get_absolute_url()) + request.user.assert_can_convert_post(post=answer) if destination == 'comment_under_question': destination_post = answer.thread._question_post() |