|
@@ -10,7 +10,7 @@ from django.utils import timezone
|
|
from misago.acl.testutils import override_acl
|
|
from misago.acl.testutils import override_acl
|
|
from misago.categories.models import Category
|
|
from misago.categories.models import Category
|
|
from misago.threads import testutils
|
|
from misago.threads import testutils
|
|
-from misago.threads.models import Post
|
|
|
|
|
|
+from misago.threads.models import Post, Thread
|
|
from misago.users.testutils import AuthenticatedUserTestCase
|
|
from misago.users.testutils import AuthenticatedUserTestCase
|
|
|
|
|
|
|
|
|
|
@@ -145,23 +145,6 @@ class BulkPatchSerializerTests(ThreadPostBulkPatchApiTestCase):
|
|
],
|
|
],
|
|
})
|
|
})
|
|
|
|
|
|
- def test_invalid_id(self):
|
|
|
|
- """api rejects too large input"""
|
|
|
|
- response = self.patch(self.api_link, {
|
|
|
|
- 'ids': [i + 1 for i in range(200)],
|
|
|
|
- 'ops': [{} for i in range(200)],
|
|
|
|
- })
|
|
|
|
-
|
|
|
|
- self.assertEqual(response.status_code, 400)
|
|
|
|
- self.assertEqual(response.json(), {
|
|
|
|
- 'ids': [
|
|
|
|
- "Ensure this field has no more than 24 elements.",
|
|
|
|
- ],
|
|
|
|
- 'ops': [
|
|
|
|
- "Ensure this field has no more than 10 elements.",
|
|
|
|
- ],
|
|
|
|
- })
|
|
|
|
-
|
|
|
|
def test_posts_not_found(self):
|
|
def test_posts_not_found(self):
|
|
"""api fails to find posts"""
|
|
"""api fails to find posts"""
|
|
posts = [
|
|
posts = [
|
|
@@ -220,7 +203,7 @@ class BulkPatchSerializerTests(ThreadPostBulkPatchApiTestCase):
|
|
|
|
|
|
class PostsAddAclApiTests(ThreadPostBulkPatchApiTestCase):
|
|
class PostsAddAclApiTests(ThreadPostBulkPatchApiTestCase):
|
|
def test_add_acl_true(self):
|
|
def test_add_acl_true(self):
|
|
- """api adds current event's acl to response"""
|
|
|
|
|
|
+ """api adds posts acls to response"""
|
|
response = self.patch(self.api_link, {
|
|
response = self.patch(self.api_link, {
|
|
'ids': self.ids,
|
|
'ids': self.ids,
|
|
'ops': [
|
|
'ops': [
|
|
@@ -238,29 +221,10 @@ class PostsAddAclApiTests(ThreadPostBulkPatchApiTestCase):
|
|
self.assertEqual(response_json[i]['id'], post.id)
|
|
self.assertEqual(response_json[i]['id'], post.id)
|
|
self.assertTrue(response_json[i]['acl'])
|
|
self.assertTrue(response_json[i]['acl'])
|
|
|
|
|
|
- def test_add_acl_false(self):
|
|
|
|
- """if value is false, api won't add acl to the response, but will set empty key"""
|
|
|
|
- response = self.patch(self.api_link, {
|
|
|
|
- 'ids': self.ids,
|
|
|
|
- 'ops': [
|
|
|
|
- {
|
|
|
|
- 'op': 'add',
|
|
|
|
- 'path': 'acl',
|
|
|
|
- 'value': False,
|
|
|
|
- },
|
|
|
|
- ]
|
|
|
|
- })
|
|
|
|
- self.assertEqual(response.status_code, 200)
|
|
|
|
-
|
|
|
|
- response_json = response.json()
|
|
|
|
- for i, post in enumerate(self.posts):
|
|
|
|
- self.assertEqual(response_json[i]['id'], post.id)
|
|
|
|
- self.assertIsNone(response_json[i]['acl'])
|
|
|
|
-
|
|
|
|
|
|
|
|
class BulkPostProtectApiTests(ThreadPostBulkPatchApiTestCase):
|
|
class BulkPostProtectApiTests(ThreadPostBulkPatchApiTestCase):
|
|
def test_protect_post(self):
|
|
def test_protect_post(self):
|
|
- """api makes it possible to protect post"""
|
|
|
|
|
|
+ """api makes it possible to protect posts"""
|
|
self.override_acl({
|
|
self.override_acl({
|
|
'can_protect_posts': 1,
|
|
'can_protect_posts': 1,
|
|
'can_edit_posts': 2,
|
|
'can_edit_posts': 2,
|
|
@@ -288,41 +252,8 @@ class BulkPostProtectApiTests(ThreadPostBulkPatchApiTestCase):
|
|
for post in Post.objects.filter(id__in=self.ids):
|
|
for post in Post.objects.filter(id__in=self.ids):
|
|
self.assertTrue(post.is_protected)
|
|
self.assertTrue(post.is_protected)
|
|
|
|
|
|
- def test_unprotect_post(self):
|
|
|
|
- """api makes it possible to unprotect protected post"""
|
|
|
|
- self.override_acl({
|
|
|
|
- 'can_protect_posts': 1,
|
|
|
|
- 'can_edit_posts': 2,
|
|
|
|
- })
|
|
|
|
-
|
|
|
|
- for post in self.posts:
|
|
|
|
- post.is_protected = True
|
|
|
|
- post.save()
|
|
|
|
-
|
|
|
|
- response = self.patch(
|
|
|
|
- self.api_link, {
|
|
|
|
- 'ids': self.ids,
|
|
|
|
- 'ops': [
|
|
|
|
- {
|
|
|
|
- 'op': 'replace',
|
|
|
|
- 'path': 'is-protected',
|
|
|
|
- 'value': False,
|
|
|
|
- },
|
|
|
|
- ]
|
|
|
|
- }
|
|
|
|
- )
|
|
|
|
- self.assertEqual(response.status_code, 200)
|
|
|
|
-
|
|
|
|
- response_json = response.json()
|
|
|
|
- for i, post in enumerate(self.posts):
|
|
|
|
- self.assertEqual(response_json[i]['id'], post.id)
|
|
|
|
- self.assertFalse(response_json[i]['is_protected'])
|
|
|
|
-
|
|
|
|
- for post in Post.objects.filter(id__in=self.ids):
|
|
|
|
- self.assertFalse(post.is_protected)
|
|
|
|
-
|
|
|
|
def test_protect_post_no_permission(self):
|
|
def test_protect_post_no_permission(self):
|
|
- """api validates permission to protect post"""
|
|
|
|
|
|
+ """api validates permission to protect posts and returns errors"""
|
|
self.override_acl({'can_protect_posts': 0})
|
|
self.override_acl({'can_protect_posts': 0})
|
|
|
|
|
|
response = self.patch(
|
|
response = self.patch(
|
|
@@ -350,116 +281,19 @@ class BulkPostProtectApiTests(ThreadPostBulkPatchApiTestCase):
|
|
for post in Post.objects.filter(id__in=self.ids):
|
|
for post in Post.objects.filter(id__in=self.ids):
|
|
self.assertFalse(post.is_protected)
|
|
self.assertFalse(post.is_protected)
|
|
|
|
|
|
- def test_unprotect_post_no_permission(self):
|
|
|
|
- """api validates permission to unprotect post"""
|
|
|
|
- for post in self.posts:
|
|
|
|
- post.is_protected = True
|
|
|
|
- post.save()
|
|
|
|
-
|
|
|
|
- self.override_acl({'can_protect_posts': 0})
|
|
|
|
-
|
|
|
|
- response = self.patch(
|
|
|
|
- self.api_link, {
|
|
|
|
- 'ids': self.ids,
|
|
|
|
- 'ops': [
|
|
|
|
- {
|
|
|
|
- 'op': 'replace',
|
|
|
|
- 'path': 'is-protected',
|
|
|
|
- 'value': False,
|
|
|
|
- },
|
|
|
|
- ]
|
|
|
|
- }
|
|
|
|
- )
|
|
|
|
- self.assertEqual(response.status_code, 400)
|
|
|
|
-
|
|
|
|
- response_json = response.json()
|
|
|
|
- for i, post in enumerate(self.posts):
|
|
|
|
- self.assertEqual(response_json[i]['id'], post.id)
|
|
|
|
- self.assertEqual(
|
|
|
|
- response_json[i]['detail'],
|
|
|
|
- ["You can't protect posts in this category."],
|
|
|
|
- )
|
|
|
|
-
|
|
|
|
- for post in Post.objects.filter(id__in=self.ids):
|
|
|
|
- self.assertTrue(post.is_protected)
|
|
|
|
-
|
|
|
|
- def test_protect_post_not_editable(self):
|
|
|
|
- """api validates if we can edit post we want to protect"""
|
|
|
|
- self.override_acl({
|
|
|
|
- 'can_protect_posts': 1,
|
|
|
|
- 'can_edit_posts': 0,
|
|
|
|
- })
|
|
|
|
-
|
|
|
|
- response = self.patch(
|
|
|
|
- self.api_link, {
|
|
|
|
- 'ids': self.ids,
|
|
|
|
- 'ops': [
|
|
|
|
- {
|
|
|
|
- 'op': 'replace',
|
|
|
|
- 'path': 'is-protected',
|
|
|
|
- 'value': True,
|
|
|
|
- },
|
|
|
|
- ]
|
|
|
|
- }
|
|
|
|
- )
|
|
|
|
- self.assertEqual(response.status_code, 400)
|
|
|
|
-
|
|
|
|
- response_json = response.json()
|
|
|
|
- for i, post in enumerate(self.posts):
|
|
|
|
- self.assertEqual(response_json[i]['id'], post.id)
|
|
|
|
- self.assertEqual(
|
|
|
|
- response_json[i]['detail'],
|
|
|
|
- ["You can't protect posts you can't edit."],
|
|
|
|
- )
|
|
|
|
-
|
|
|
|
- for post in Post.objects.filter(id__in=self.ids):
|
|
|
|
- self.assertFalse(post.is_protected)
|
|
|
|
-
|
|
|
|
- def test_unprotect_post_not_editable(self):
|
|
|
|
- """api validates if we can edit post we want to protect"""
|
|
|
|
- for post in self.posts:
|
|
|
|
- post.is_protected = True
|
|
|
|
- post.save()
|
|
|
|
|
|
|
|
-
|
|
|
|
- self.override_acl({
|
|
|
|
- 'can_protect_posts': 1,
|
|
|
|
- 'can_edit_posts': 0,
|
|
|
|
- })
|
|
|
|
-
|
|
|
|
- response = self.patch(
|
|
|
|
- self.api_link, {
|
|
|
|
- 'ids': self.ids,
|
|
|
|
- 'ops': [
|
|
|
|
- {
|
|
|
|
- 'op': 'replace',
|
|
|
|
- 'path': 'is-protected',
|
|
|
|
- 'value': False,
|
|
|
|
- },
|
|
|
|
- ]
|
|
|
|
- }
|
|
|
|
- )
|
|
|
|
- self.assertEqual(response.status_code, 400)
|
|
|
|
-
|
|
|
|
- response_json = response.json()
|
|
|
|
- for i, post in enumerate(self.posts):
|
|
|
|
- self.assertEqual(response_json[i]['id'], post.id)
|
|
|
|
- self.assertEqual(
|
|
|
|
- response_json[i]['detail'],
|
|
|
|
- ["You can't protect posts you can't edit."],
|
|
|
|
- )
|
|
|
|
-
|
|
|
|
- for post in Post.objects.filter(id__in=self.ids):
|
|
|
|
- self.assertTrue(post.is_protected)
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-class PostsApproveApiTests(ThreadPostBulkPatchApiTestCase):
|
|
|
|
|
|
+class BulkPostsApproveApiTests(ThreadPostBulkPatchApiTestCase):
|
|
def test_approve_post(self):
|
|
def test_approve_post(self):
|
|
- """api makes it possible to approve post"""
|
|
|
|
|
|
+ """api resyncs thread and categories on posts approval"""
|
|
for post in self.posts:
|
|
for post in self.posts:
|
|
post.is_unapproved = True
|
|
post.is_unapproved = True
|
|
post.save()
|
|
post.save()
|
|
|
|
|
|
|
|
+ self.thread.synchronize()
|
|
|
|
+ self.thread.save()
|
|
|
|
+
|
|
|
|
+ self.assertNotIn(self.thread.last_post_id, self.ids)
|
|
|
|
+
|
|
self.override_acl({'can_approve_content': 1})
|
|
self.override_acl({'can_approve_content': 1})
|
|
|
|
|
|
response = self.patch(
|
|
response = self.patch(
|
|
@@ -484,214 +318,8 @@ class PostsApproveApiTests(ThreadPostBulkPatchApiTestCase):
|
|
for post in Post.objects.filter(id__in=self.ids):
|
|
for post in Post.objects.filter(id__in=self.ids):
|
|
self.assertFalse(post.is_unapproved)
|
|
self.assertFalse(post.is_unapproved)
|
|
|
|
|
|
- def test_unapprove_post(self):
|
|
|
|
- """unapproving posts is not supported by api"""
|
|
|
|
- self.override_acl({'can_approve_content': 1})
|
|
|
|
-
|
|
|
|
- response = self.patch(
|
|
|
|
- self.api_link, {
|
|
|
|
- 'ids': self.ids,
|
|
|
|
- 'ops': [
|
|
|
|
- {
|
|
|
|
- 'op': 'replace',
|
|
|
|
- 'path': 'is-unapproved',
|
|
|
|
- 'value': True,
|
|
|
|
- },
|
|
|
|
- ]
|
|
|
|
- }
|
|
|
|
- )
|
|
|
|
- self.assertEqual(response.status_code, 400)
|
|
|
|
-
|
|
|
|
- response_json = response.json()
|
|
|
|
- for i, post in enumerate(self.posts):
|
|
|
|
- self.assertEqual(response_json[i]['id'], post.id)
|
|
|
|
- self.assertEqual(
|
|
|
|
- response_json[i]['detail'],
|
|
|
|
- ["Content approval can't be reversed."],
|
|
|
|
- )
|
|
|
|
-
|
|
|
|
- for post in Post.objects.filter(id__in=self.ids):
|
|
|
|
- self.assertFalse(post.is_unapproved)
|
|
|
|
-
|
|
|
|
- def test_approve_post_no_permission(self):
|
|
|
|
- """api validates approval permission"""
|
|
|
|
- for post in self.posts:
|
|
|
|
- post.poster = self.user
|
|
|
|
- post.is_unapproved = True
|
|
|
|
- post.save()
|
|
|
|
-
|
|
|
|
- self.override_acl({'can_approve_content': 0})
|
|
|
|
-
|
|
|
|
- response = self.patch(
|
|
|
|
- self.api_link, {
|
|
|
|
- 'ids': self.ids,
|
|
|
|
- 'ops': [
|
|
|
|
- {
|
|
|
|
- 'op': 'replace',
|
|
|
|
- 'path': 'is-unapproved',
|
|
|
|
- 'value': False,
|
|
|
|
- },
|
|
|
|
- ]
|
|
|
|
- }
|
|
|
|
- )
|
|
|
|
- self.assertEqual(response.status_code, 400)
|
|
|
|
-
|
|
|
|
- response_json = response.json()
|
|
|
|
- for i, post in enumerate(self.posts):
|
|
|
|
- self.assertEqual(response_json[i]['id'], post.id)
|
|
|
|
- self.assertEqual(
|
|
|
|
- response_json[i]['detail'],
|
|
|
|
- ["You can't approve posts in this category."],
|
|
|
|
- )
|
|
|
|
-
|
|
|
|
- for post in Post.objects.filter(id__in=self.ids):
|
|
|
|
- self.assertTrue(post.is_unapproved)
|
|
|
|
-
|
|
|
|
- def test_approve_post_closed_thread_no_permission(self):
|
|
|
|
- """api validates approval permission in closed threads"""
|
|
|
|
- for post in self.posts:
|
|
|
|
- post.is_unapproved = True
|
|
|
|
- post.save()
|
|
|
|
-
|
|
|
|
- self.thread.is_closed = True
|
|
|
|
- self.thread.save()
|
|
|
|
-
|
|
|
|
- self.override_acl({
|
|
|
|
- 'can_approve_content': 1,
|
|
|
|
- 'can_close_threads': 0,
|
|
|
|
- })
|
|
|
|
-
|
|
|
|
- response = self.patch(
|
|
|
|
- self.api_link, {
|
|
|
|
- 'ids': self.ids,
|
|
|
|
- 'ops': [
|
|
|
|
- {
|
|
|
|
- 'op': 'replace',
|
|
|
|
- 'path': 'is-unapproved',
|
|
|
|
- 'value': False,
|
|
|
|
- },
|
|
|
|
- ]
|
|
|
|
- }
|
|
|
|
- )
|
|
|
|
- self.assertEqual(response.status_code, 400)
|
|
|
|
-
|
|
|
|
- response_json = response.json()
|
|
|
|
- for i, post in enumerate(self.posts):
|
|
|
|
- self.assertEqual(response_json[i]['id'], post.id)
|
|
|
|
- self.assertEqual(
|
|
|
|
- response_json[i]['detail'],
|
|
|
|
- ["This thread is closed. You can't approve posts in it."],
|
|
|
|
- )
|
|
|
|
-
|
|
|
|
- for post in Post.objects.filter(id__in=self.ids):
|
|
|
|
- self.assertTrue(post.is_unapproved)
|
|
|
|
-
|
|
|
|
- def test_approve_post_closed_category_no_permission(self):
|
|
|
|
- """api validates approval permission in closed categories"""
|
|
|
|
- for post in self.posts:
|
|
|
|
- post.is_unapproved = True
|
|
|
|
- post.save()
|
|
|
|
-
|
|
|
|
- self.category.is_closed = True
|
|
|
|
- self.category.save()
|
|
|
|
|
|
+ thread = Thread.objects.get(pk=self.thread.pk)
|
|
|
|
+ self.assertIn(thread.last_post_id, self.ids)
|
|
|
|
|
|
- self.override_acl({
|
|
|
|
- 'can_approve_content': 1,
|
|
|
|
- 'can_close_threads': 0,
|
|
|
|
- })
|
|
|
|
-
|
|
|
|
- response = self.patch(
|
|
|
|
- self.api_link, {
|
|
|
|
- 'ids': self.ids,
|
|
|
|
- 'ops': [
|
|
|
|
- {
|
|
|
|
- 'op': 'replace',
|
|
|
|
- 'path': 'is-unapproved',
|
|
|
|
- 'value': False,
|
|
|
|
- },
|
|
|
|
- ]
|
|
|
|
- }
|
|
|
|
- )
|
|
|
|
- self.assertEqual(response.status_code, 400)
|
|
|
|
-
|
|
|
|
- response_json = response.json()
|
|
|
|
- for i, post in enumerate(self.posts):
|
|
|
|
- self.assertEqual(response_json[i]['id'], post.id)
|
|
|
|
- self.assertEqual(
|
|
|
|
- response_json[i]['detail'],
|
|
|
|
- ["This category is closed. You can't approve posts in it."],
|
|
|
|
- )
|
|
|
|
-
|
|
|
|
- for post in Post.objects.filter(id__in=self.ids):
|
|
|
|
- self.assertTrue(post.is_unapproved)
|
|
|
|
-
|
|
|
|
- def test_approve_first_post(self):
|
|
|
|
- """api approve first post fails"""
|
|
|
|
- for post in self.posts:
|
|
|
|
- post.is_unapproved = True
|
|
|
|
- post.save()
|
|
|
|
-
|
|
|
|
- self.thread.set_first_post(self.posts[0])
|
|
|
|
- self.thread.save()
|
|
|
|
-
|
|
|
|
- self.override_acl({'can_approve_content': 1})
|
|
|
|
-
|
|
|
|
- response = self.patch(
|
|
|
|
- self.api_link, {
|
|
|
|
- 'ids': self.ids,
|
|
|
|
- 'ops': [
|
|
|
|
- {
|
|
|
|
- 'op': 'replace',
|
|
|
|
- 'path': 'is-unapproved',
|
|
|
|
- 'value': False,
|
|
|
|
- },
|
|
|
|
- ]
|
|
|
|
- }
|
|
|
|
- )
|
|
|
|
- self.assertEqual(response.status_code, 400)
|
|
|
|
-
|
|
|
|
- response_json = response.json()
|
|
|
|
- self.assertEqual(response_json[0], {
|
|
|
|
- 'id': self.posts[0].id,
|
|
|
|
- 'detail': ["You can't approve thread's first post."],
|
|
|
|
- })
|
|
|
|
-
|
|
|
|
- for post in Post.objects.filter(id__in=self.ids):
|
|
|
|
- if post.id == self.ids[0]:
|
|
|
|
- self.assertTrue(post.is_unapproved)
|
|
|
|
- else:
|
|
|
|
- self.assertFalse(post.is_unapproved)
|
|
|
|
-
|
|
|
|
- def test_approve_hidden_post(self):
|
|
|
|
- """api approve hidden post fails"""
|
|
|
|
- for post in self.posts:
|
|
|
|
- post.is_unapproved = True
|
|
|
|
- post.is_hidden = True
|
|
|
|
- post.save()
|
|
|
|
-
|
|
|
|
- self.override_acl({'can_approve_content': 1})
|
|
|
|
-
|
|
|
|
- response = self.patch(
|
|
|
|
- self.api_link, {
|
|
|
|
- 'ids': self.ids,
|
|
|
|
- 'ops': [
|
|
|
|
- {
|
|
|
|
- 'op': 'replace',
|
|
|
|
- 'path': 'is-unapproved',
|
|
|
|
- 'value': False,
|
|
|
|
- },
|
|
|
|
- ]
|
|
|
|
- }
|
|
|
|
- )
|
|
|
|
- self.assertEqual(response.status_code, 400)
|
|
|
|
-
|
|
|
|
- response_json = response.json()
|
|
|
|
- for i, post in enumerate(self.posts):
|
|
|
|
- self.assertEqual(response_json[i]['id'], post.id)
|
|
|
|
- self.assertEqual(
|
|
|
|
- response_json[i]['detail'],
|
|
|
|
- ["You can't approve posts the content you can't see."],
|
|
|
|
- )
|
|
|
|
-
|
|
|
|
- for post in Post.objects.filter(id__in=self.ids):
|
|
|
|
- self.assertTrue(post.is_unapproved)
|
|
|
|
|
|
+ category = Category.objects.get(pk=self.category.pk)
|
|
|
|
+ self.assertEqual(category.posts, 4)
|