summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeny Fadeev <evgeny.fadeev@gmail.com>2010-08-09 22:08:29 -0400
committerEvgeny Fadeev <evgeny.fadeev@gmail.com>2010-08-09 22:08:29 -0400
commit2d32a08751e699456128489cd2606c4aa015796a (patch)
treecf49177f6b8fc36c0bd198f9e7bb73f445492c66
parentf237fdf287e007d78ecc9996bbb87383cfc8d493 (diff)
downloadaskbot-2d32a08751e699456128489cd2606c4aa015796a.tar.gz
askbot-2d32a08751e699456128489cd2606c4aa015796a.tar.bz2
askbot-2d32a08751e699456128489cd2606c4aa015796a.zip
accept answer function is now under moderation rules
-rw-r--r--askbot/models/__init__.py60
-rw-r--r--askbot/models/answer.py1
-rw-r--r--askbot/tests/db_api_tests.py20
-rw-r--r--askbot/tests/permission_assertion_tests.py83
-rw-r--r--askbot/views/commands.py27
5 files changed, 163 insertions, 28 deletions
diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py
index 316e1a77..0b987ea0 100644
--- a/askbot/models/__init__.py
+++ b/askbot/models/__init__.py
@@ -155,6 +155,37 @@ def _assert_user_can(
assert(error_message is not None)
raise django_exceptions.PermissionDenied(error_message)
+def user_assert_can_unaccept_best_answer(self, answer = None):
+ assert(isinstance(answer, Answer))
+ if self.is_blocked():
+ error_message = _(
+ 'Sorry, you cannot accept or unaccept best answers ' + \
+ 'because your account is blocked'
+ )
+ elif self.is_suspended():
+ error_message = _(
+ 'Sorry, you cannot accept or unaccept best answers ' + \
+ 'because your account is suspended'
+ )
+ elif self == answer.question.get_owner():
+ if self == answer.get_owner():
+ error_message = _(
+ 'Sorry, you cannot accept or unaccept your own answer ' + \
+ 'to your own question'
+ )
+ else:
+ return #assertion success
+ else:
+ error_message = _(
+ 'Sorry, only original author of the question ' + \
+ ' - %(username)s - can accept the best answer'
+ ) % {'username': answer.get_owner().username}
+
+ raise django_exceptions.PermissionDenied(error_message)
+
+def user_assert_can_accept_best_answer(self, answer = None):
+ assert(isinstance(answer, Answer))
+ self.assert_can_unaccept_best_answer(answer)
def user_assert_can_vote_for_post(
self,
@@ -668,6 +699,26 @@ def user_retag_question(
tagnames = tags,
)
+@auto_now_timestamp
+def user_accept_best_answer(self, answer = None, timestamp = None):
+ self.assert_can_accept_best_answer(answer)
+ if answer.accepted == True:
+ return
+
+ prev_accepted_answers = answer.question.answers.filter(accepted = True)
+ for prev_answer in prev_accepted_answers:
+ auth.onAnswerAcceptCanceled(prev_answer, self)
+
+ auth.onAnswerAccept(answer, self)
+
+@auto_now_timestamp
+def user_unaccept_best_answer(self, answer = None, timestamp = None):
+ self.assert_can_unaccept_best_answer(answer)
+ if answer.accepted == False:
+ return
+ auth.onAnswerAcceptCanceled(answer, self)
+
+@auto_now_timestamp
def user_delete_comment(
self,
comment = None,
@@ -676,6 +727,7 @@ def user_delete_comment(
self.assert_can_delete_comment(comment = comment)
comment.delete()
+@auto_now_timestamp
def user_delete_answer(
self,
answer = None,
@@ -685,6 +737,7 @@ def user_delete_answer(
#todo - move onDeleted method where appropriate
auth.onDeleted(answer, self, timestamp = timestamp)
+@auto_now_timestamp
def user_delete_question(
self,
question = None,
@@ -1281,6 +1334,8 @@ User.add_to_class('delete_answer', user_delete_answer)
User.add_to_class('restore_post', user_restore_post)
User.add_to_class('close_question', user_close_question)
User.add_to_class('reopen_question', user_reopen_question)
+User.add_to_class('accept_best_answer', user_accept_best_answer)
+User.add_to_class('unaccept_best_answer', user_unaccept_best_answer)
#assertions
User.add_to_class('assert_can_vote_for_post', user_assert_can_vote_for_post)
@@ -1304,6 +1359,11 @@ 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_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)
+User.add_to_class(
+ 'assert_can_unaccept_best_answer',
+ user_assert_can_unaccept_best_answer
+ )
#todo: move this to askbot/utils ??
def format_instant_notification_body(
diff --git a/askbot/models/answer.py b/askbot/models/answer.py
index c0107fee..7bb006b1 100644
--- a/askbot/models/answer.py
+++ b/askbot/models/answer.py
@@ -74,6 +74,7 @@ class AnswerManager(models.Manager):
Retrieves visibile answers for the given question. Delete answers
are only visibile to the person who deleted them.
"""
+ #todo: there is this odd query used?
if user is None or not user.is_authenticated():
return self.filter(question=question, deleted=False)
diff --git a/askbot/tests/db_api_tests.py b/askbot/tests/db_api_tests.py
index 8aa7fa78..0dbe4663 100644
--- a/askbot/tests/db_api_tests.py
+++ b/askbot/tests/db_api_tests.py
@@ -7,23 +7,31 @@ from askbot.tests.utils import AskbotTestCase
class DBApiTests(AskbotTestCase):
- def test_flag_question(self):
+ def setUp(self):
self.create_user()
- question = self.post_question()
+ self.create_user(username = 'other_user')
+ self.question = self.post_question()
+
+ def test_flag_question(self):
self.user.set_status('m')
- self.user.flag_post(question)
+ self.user.flag_post(self.question)
self.assertEquals(
len(self.user.flaggeditems.all()),
1
)
def test_flag_answer(self):
- self.create_user()
- question = self.post_question()
- answer = self.post_answer(question = question)
+ answer = self.post_answer(question = self.question)
self.user.set_status('m')
self.user.flag_post(answer)
self.assertEquals(
len(self.user.flaggeditems.all()),
1
)
+
+ def test_accept_best_answer(self):
+ answer = self.post_answer(
+ question = self.question,
+ user = self.other_user
+ )
+ self.user.accept_best_answer(answer)
diff --git a/askbot/tests/permission_assertion_tests.py b/askbot/tests/permission_assertion_tests.py
index 65ba6f47..0918e8b5 100644
--- a/askbot/tests/permission_assertion_tests.py
+++ b/askbot/tests/permission_assertion_tests.py
@@ -1197,6 +1197,89 @@ class CommentPermissionAssertionTests(PermissionAssertionTestCase):
#def user_assert_can_close_question(self, question = None):
#def user_assert_can_retag_questions(self):
+class AcceptBestAnswerPermissionAssertionTests(utils.AskbotTestCase):
+
+ def setUp(self):
+ self.create_user()
+ self.create_user(username = 'other_user')
+ self.question = self.post_question()
+
+ def other_post_answer(self):
+ self.answer = self.post_answer(
+ question = self.question,
+ user = self.other_user
+ )
+
+ def user_post_answer(self):
+ self.answer = self.post_answer(
+ question = self.question,
+ user = self.user
+ )
+
+ def assert_user_can(self, user = None):
+ if user is None:
+ user = self.user
+ user.assert_can_accept_best_answer(self.answer)
+
+ def assert_user_cannot(self, user = None):
+ if user is None:
+ user = self.user
+ self.assertRaises(
+ exceptions.PermissionDenied,
+ user.assert_can_accept_best_answer,
+ answer = self.answer
+ )
+
+ def test_question_owner_can_accept_others_answer(self):
+ self.other_post_answer()
+ self.assert_user_can()
+
+ def test_suspended_question_owner_cannot_accept_others_answer(self):
+ self.other_post_answer()
+ self.user.set_status('s')
+ self.assert_user_cannot()
+
+ def test_blocked_question_owner_cannot_accept_others_answer(self):
+ self.other_post_answer()
+ self.user.set_status('b')
+ self.assert_user_cannot()
+
+ def test_answer_owner_cannot_accept_answer(self):
+ self.other_post_answer()
+ self.assert_user_cannot(user = self.other_user)
+
+ def test_question_and_answer_owner_cannot_accept_answer(self):
+ self.user_post_answer()
+ self.assert_user_cannot()
+
+ def test_high_rep_other_user_cannot_accept_answer(self):
+ self.other_post_answer()
+ self.create_user(username = 'third_user')
+ self.third_user.reputation = 1000000
+ self.assert_user_cannot(user = self.third_user)
+
+ def test_moderator_cannot_accept_others_answer(self):
+ self.other_post_answer()
+ self.create_user(username = 'third_user')
+ self.third_user.set_status('m')
+ self.assert_user_cannot(user = self.third_user)
+
+ def test_moderator_cannot_accept_own_answer(self):
+ self.other_post_answer()
+ self.other_user.set_status('m')
+ self.assert_user_cannot(user = self.other_user)
+
+ def test_admin_cannot_accept_others_answer(self):
+ self.other_post_answer()
+ self.create_user(username = 'third_user')
+ self.third_user.is_superuser = True
+ self.assert_user_cannot(user = self.third_user)
+
+ def test_admin_cannot_accept_own_answer(self):
+ self.other_post_answer()
+ self.other_user.is_superuser = True
+ self.assert_user_cannot(user = self.other_user)
+
class VotePermissionAssertionTests(PermissionAssertionTestCase):
"""Tests permission for voting
"""
diff --git a/askbot/views/commands.py b/askbot/views/commands.py
index b52bba1d..ab49dd88 100644
--- a/askbot/views/commands.py
+++ b/askbot/views/commands.py
@@ -138,31 +138,14 @@ def vote(request, id):
if vote_type == '0':
if request.user.is_authenticated():
answer_id = request.POST.get('postId')
- answer = get_object_or_404(Answer, id=answer_id)
+ answer = get_object_or_404(Answer, id = answer_id)
question = answer.question
# make sure question author is current user
- if question.author == request.user:
- # answer user who is also question author is not allow to accept answer
- if answer.author == question.author:
- response_data['success'] = 0
- response_data['allowed'] = -1
- # check if answer has been accepted already
- elif answer.accepted:
- auth.onAnswerAcceptCanceled(answer, request.user)
- response_data['status'] = 1
- else:
- # set other answers in this question not accepted first
- for answer_of_question in Answer.objects.get_answers_from_question(question, request.user):
- if answer_of_question != answer and answer_of_question.accepted:
- auth.onAnswerAcceptCanceled(answer_of_question, request.user)
-
- #make sure retrieve data again after above author changes, they may have related data
- answer = get_object_or_404(Answer, id=answer_id)
- auth.onAnswerAccept(answer, request.user)
+ if answer.accepted:
+ request.user.unaccept_best_answer(answer)
+ response_data['status'] = 1 #cancelation
else:
- raise exceptions.PermissionDenied(
- 'Sorry, only question owner can accept the answer'
- )
+ request.user.accept_best_answer(answer)
else:
raise exceptions.PermissionDenied(
_('Sorry, but anonymous users cannot accept answers')