def dispatch(self, request, *args, **kwargs): relations = ['forum'] thread = self.fetch_thread(request, select_related=relations, **kwargs) forum = thread.forum self.check_forum_permissions(request, forum) self.check_thread_permissions(request, thread) self.allow_action(thread) if not request.is_ajax(): response = render(request, 'misago/errorpages/wrong_way.html') response.status_code = 405 return response queryset = exclude_invisible_posts( thread.post_set, request.user, forum) queryset = self.filter_posts_queryset(queryset) final_queryset = queryset.select_related('poster').order_by('-id')[:15] return self.render(request, { 'forum': forum, 'thread': thread, 'posts_count': queryset.count(), 'posts': final_queryset.iterator() })
def clean_posts_for_split(request, thread): posts_ids = clean_ids_list( request.data.get('posts', []), _("One or more post ids received were invalid."), ) if not posts_ids: raise PermissionDenied(_("You have to specify at least one post to split.")) elif len(posts_ids) > SPLIT_LIMIT: message = ungettext( "No more than %(limit)s post can be split at single time.", "No more than %(limit)s posts can be split at single time.", SPLIT_LIMIT, ) raise PermissionDenied(message % {'limit': SPLIT_LIMIT}) posts_queryset = exclude_invisible_posts(request.user, thread.category, thread.post_set) posts_queryset = posts_queryset.filter(id__in=posts_ids).order_by('id') posts = [] for post in posts_queryset: post.category = thread.category post.thread = thread allow_split_post(request.user, post) posts.append(post) if len(posts) != len(posts_ids): raise PermissionDenied(_("One or more posts to split could not be found.")) return posts
def validate_posts(self, data): data = list(set(data)) if len(data) > POSTS_MOVE_LIMIT: message = ungettext( "No more than %(limit)s post can be moved at single time.", "No more than %(limit)s posts can be moved at single time.", POSTS_MOVE_LIMIT, ) raise serializers.ValidationError(message % {'limit': POSTS_MOVE_LIMIT}) request = self.context['request'] thread = self.context['thread'] posts_queryset = exclude_invisible_posts(request.user, thread.category, thread.post_set) posts_queryset = posts_queryset.filter(id__in=data).order_by('id') posts = [] for post in posts_queryset: post.category = thread.category post.thread = thread try: allow_move_post(request.user, post) posts.append(post) except PermissionDenied as e: raise serializers.ValidationError(six.text_type(e)) if len(posts) != len(data): raise serializers.ValidationError(_("One or more posts to move could not be found.")) self.posts_cache = posts return data
def real_dispatch(self, request, post): post_id = post.id permissions.allow_delete_post(request.user, post) moderation.delete_post(request.user, post) post.thread.synchronize() post.thread.save() post.forum.synchronize() post.forum.save() posts_queryset = exclude_invisible_posts(post.thread.post_set, request.user, post.forum) posts_queryset = posts_queryset.select_related('thread', 'forum') if post_id < post.thread.last_post_id: target_post = posts_queryset.order_by('id').filter(id__gt=post_id) else: target_post = posts_queryset.order_by('-id').filter(id__lt=post_id) target_post = target_post[:1][0] target_post.thread.forum = target_post.forum add_acl(request.user, target_post.forum) add_acl(request.user, target_post.thread) add_acl(request.user, target_post) messages.success(request, _("Post has been deleted.")) return self.redirect_to_post(request.user, target_post)
def dispatch(self, request, *args, **kwargs): relations = ['forum'] thread = self.fetch_thread(request, select_related=relations, **kwargs) forum = thread.forum self.check_forum_permissions(request, forum) self.check_thread_permissions(request, thread) self.allow_action(thread) if not request.is_ajax(): response = render(request, 'misago/errorpages/wrong_way.html') response.status_code = 405 return response queryset = exclude_invisible_posts(thread.post_set, request.user, forum) queryset = self.filter_posts_queryset(queryset) final_queryset = queryset.select_related('poster').order_by('-id')[:15] return self.render( request, { 'forum': forum, 'thread': thread, 'posts_count': queryset.count(), 'posts': final_queryset.iterator() })
def validate_posts(self, data): if len(data) > POSTS_LIMIT: message = ngettext( "No more than %(limit)s post can be deleted at single time.", "No more than %(limit)s posts can be deleted at single time.", POSTS_LIMIT, ) raise ValidationError(message % {'limit': POSTS_LIMIT}) user = self.context['user'] thread = self.context['thread'] posts_queryset = exclude_invisible_posts(user, thread.category, thread.post_set) posts_queryset = posts_queryset.filter(id__in=data).order_by('id') posts = [] for post in posts_queryset: post.category = thread.category post.thread = thread if post.is_event: allow_delete_event(user, post) else: allow_delete_best_answer(user, post) allow_delete_post(user, post) posts.append(post) if len(posts) != len(data): raise PermissionDenied(_("One or more posts to delete could not be found.")) return posts
def make_read_aware(user, categories): if not categories: return if not hasattr(categories, '__iter__'): categories = [categories] make_read(categories) if user.is_anonymous: return threads = Thread.objects.filter(category__in=categories) threads = exclude_invisible_threads(user, categories, threads) queryset = Post.objects.filter( category__in=categories, thread__in=threads, posted_on__gt=get_cutoff_date(user), ).values_list('category', flat=True).distinct() queryset = queryset.exclude(id__in=user.postread_set.values('post')) queryset = exclude_invisible_posts(user, categories, queryset) unread_categories = list(queryset) for category in categories: if category.pk in unread_categories: category.is_read = False category.is_new = True
def clean_posts_for_move(request, thread): posts_ids = clean_ids_list( request.data.get('posts', []), _("One or more post ids received were invalid."), ) if not posts_ids: raise PermissionDenied( _("You have to specify at least one post to move.")) elif len(posts_ids) > MOVE_LIMIT: message = ungettext( "No more than %(limit)s post can be moved at single time.", "No more than %(limit)s posts can be moved at single time.", MOVE_LIMIT, ) raise PermissionDenied(message % {'limit': MOVE_LIMIT}) posts_queryset = exclude_invisible_posts(request.user, thread.category, thread.post_set) posts_queryset = posts_queryset.filter(id__in=posts_ids).order_by('id') posts = [] for post in posts_queryset: post.category = thread.category post.thread = thread allow_move_post(request.user, post) posts.append(post) if len(posts) != len(posts_ids): raise PermissionDenied( _("One or more posts to move could not be found.")) return posts
def validate_posts(self, data): if len(data) > POSTS_LIMIT: message = ungettext( "No more than %(limit)s post can be split at single time.", "No more than %(limit)s posts can be split at single time.", POSTS_LIMIT, ) raise ValidationError(message % {'limit': POSTS_LIMIT}) thread = self.context['thread'] user = self.context['user'] posts_queryset = exclude_invisible_posts(user, thread.category, thread.post_set) posts_queryset = posts_queryset.filter(id__in=data).order_by('id') posts = [] for post in posts_queryset: post.category = thread.category post.thread = thread try: allow_split_post(user, post) except PermissionDenied as e: raise ValidationError(e) posts.append(post) if len(posts) != len(data): raise ValidationError( _("One or more posts to split could not be found.")) return posts
def validate_posts(self, data): data = list(set(data)) if len(data) < 2: raise ValidationError(self.error_empty_or_required) if len(data) > POSTS_LIMIT: message = ungettext( "No more than %(limit)s post can be merged at single time.", "No more than %(limit)s posts can be merged at single time.", POSTS_LIMIT, ) raise ValidationError(message % {'limit': POSTS_LIMIT}) user = self.context['user'] thread = self.context['thread'] posts_queryset = exclude_invisible_posts(user, thread.category, thread.post_set) posts_queryset = posts_queryset.filter(id__in=data).order_by('id') posts = [] for post in posts_queryset: post.category = thread.category post.thread = thread try: allow_merge_post(user, post) except PermissionDenied as e: raise ValidationError(e) if not posts: posts.append(post) continue authorship_error = _( "Posts made by different users can't be merged.") if post.poster_id != posts[0].poster_id: raise serializers.ValidationError(authorship_error) elif (post.poster_id is None and posts[0].poster_id is None and post.poster_name != posts[0].poster_name): raise serializers.ValidationError(authorship_error) if posts[0].is_first_post and post.is_best_answer: raise serializers.ValidationError( _("Post marked as best answer can't be merged with thread's first post." )) if not posts[0].is_first_post: if (posts[0].is_hidden != post.is_hidden or posts[0].is_unapproved != post.is_unapproved): raise serializers.ValidationError( _("Posts with different visibility can't be merged.")) posts.append(post) if len(posts) != len(data): raise ValidationError( _("One or more posts to merge could not be found.")) return posts
def make_read_aware(user, threads): if not threads: return if not hasattr(threads, '__iter__'): threads = [threads] make_read(threads) if user.is_anonymous: return categories = [t.category for t in threads] queryset = Post.objects.filter( thread__in=threads, posted_on__gt=get_cutoff_date(user), ).values_list('thread', flat=True).distinct() queryset = queryset.exclude(id__in=user.postread_set.values('post')) queryset = exclude_invisible_posts(user, categories, queryset) unread_threads = list(queryset) for thread in threads: if thread.pk in unread_threads: thread.is_read = False thread.is_new = True
def real_dispatch(self, request, post): post_id = post.id permissions.allow_delete_post(request.user, post) moderation.delete_post(request.user, post) post.thread.synchronize() post.thread.save() post.forum.synchronize() post.forum.save() posts_queryset = exclude_invisible_posts(post.thread.post_set, request.user, post.forum) posts_queryset = posts_queryset.select_related('thread', 'forum') if post_id < post.thread.last_post_id: target_post = posts_queryset.order_by('id').filter(id__gt=post_id) else: target_post = posts_queryset.order_by('-id').filter(id__lt=post_id) target_post = target_post[:1][0] target_post.thread.forum = target_post.forum add_acl(request.user, target_post.forum) add_acl(request.user, target_post.thread) add_acl(request.user, target_post) messages.success(request, _("Post has been deleted.")) return self.redirect_to_post(request.user, target_post)
def filter_read_threads_queryset(user, categories, list_type, queryset): # grab cutoffs for categories cutoff_date = get_cutoff_date(user) visible_posts = Post.objects.filter(posted_on__gt=cutoff_date) visible_posts = exclude_invisible_posts(user, categories, visible_posts) queryset = queryset.filter( id__in=visible_posts.distinct().values('thread')) read_posts = visible_posts.filter(id__in=user.postread_set.values('post')) if list_type == 'new': # new threads have no entry in reads table return queryset.exclude(id__in=read_posts.distinct().values('thread')) if list_type == 'unread': # unread threads were read in past but have new posts unread_posts = visible_posts.exclude( id__in=user.postread_set.values('post')) queryset = queryset.filter( id__in=read_posts.distinct().values('thread')) queryset = queryset.filter( id__in=unread_posts.distinct().values('thread')) return queryset
def clean_posts_for_patch(request, thread): if not isinstance(request.data, dict): raise PermissionDenied(_("Bulk PATCH request should be a dict with ids and ops keys.")) # todo: move this ids list cleanup step to utility try: posts_ids = list(map(int, request.data.get('ids', []))) except (ValueError, TypeError): raise PermissionDenied(_("One or more post ids received were invalid.")) if not posts_ids: raise PermissionDenied(_("You have to specify at least one post to update.")) elif len(posts_ids) > PATCH_LIMIT: message = ungettext( "No more than %(limit)s post can be updated at single time.", "No more than %(limit)s posts can be updated at single time.", PATCH_LIMIT, ) raise PermissionDenied(message % {'limit': PATCH_LIMIT}) posts_queryset = exclude_invisible_posts(request.user, thread.category, thread.post_set) posts_queryset = posts_queryset.filter(id__in=posts_ids).order_by('id') posts = [] for post in posts_queryset: post.category = thread.category post.thread = thread posts.append(post) if len(posts) != len(posts_ids): raise PermissionDenied(_("One or more posts to update could not be found.")) return posts
def get_posts_queryset(self, request, thread): queryset = thread.post_set.select_related( 'poster', 'poster__rank', 'poster__ban_cache', 'poster__online_tracker', ).filter(is_event=False).order_by('id') return exclude_invisible_posts(request.user, thread.category, queryset)
def get_posts_queryset(self, request, thread): queryset = thread.post_set.select_related( 'poster', 'poster__rank', 'poster__ban_cache', 'poster__online_tracker', ).filter(is_event=False).order_by('id') return exclude_invisible_posts(request.user, thread.category, queryset)
def get_posts_queryset(self, user, forum, thread): queryset = thread.post_set.select_related( 'poster', 'poster__rank', 'poster__ban_cache', 'poster__online_tracker' ) return exclude_invisible_posts(queryset, user, forum).order_by('id')
def get_events_queryset(self, request, thread, limit, first_post=None, last_post=None): queryset = thread.post_set.select_related('poster').filter(is_event=True) if first_post: queryset = queryset.filter(pk__gt=first_post.pk) if last_post: queryset = queryset.filter(pk__lt=last_post.pk) queryset = exclude_invisible_posts(request.user, thread.category, queryset) return list(queryset.order_by('-id')[:limit])
def get(self, request, pk, slug, **kwargs): thread = self.get_thread(request, pk, slug).unwrap() self.test_permissions(request, thread) posts_queryset = exclude_invisible_posts(request.user, thread.category, thread.post_set) target_post = self.get_target_post(thread, posts_queryset.order_by('id'), **kwargs) target_page = self.compute_post_page(target_post, posts_queryset) return self.get_redirect(thread, target_post, target_page)
def get(self, request, pk, slug, **kwargs): thread = self.get_thread(request, pk, slug).unwrap() self.test_permissions(request, thread) posts_queryset = exclude_invisible_posts(request.user, thread.category, thread.post_set) target_post = self.get_target_post(request.user, thread, posts_queryset.order_by('id'), **kwargs) target_page = self.compute_post_page(target_post, posts_queryset) return self.get_redirect(thread, target_post, target_page)
def validate_posts(self, data): data = list(set(data)) if len(data) < 2: raise serializers.ValidationError(_("You have to select at least two posts to merge.")) if len(data) > POSTS_MERGE_LIMIT: message = ungettext( "No more than %(limit)s post can be merged at single time.", "No more than %(limit)s posts can be merged at single time.", POSTS_MERGE_LIMIT, ) raise serializers.ValidationError(message % {'limit': POSTS_MERGE_LIMIT}) user = self.context['user'] thread = self.context['thread'] posts_queryset = exclude_invisible_posts(user, thread.category, thread.post_set) posts_queryset = posts_queryset.filter(id__in=data).order_by('id') posts = [] for post in posts_queryset: post.category = thread.category post.thread = thread try: allow_merge_post(user, post) except PermissionDenied as e: raise serializers.ValidationError(six.text_type(e)) if not posts: posts.append(post) else: authorship_error = _("Posts made by different users can't be merged.") if posts[0].poster_id: if post.poster_id != posts[0].poster_id: raise serializers.ValidationError(authorship_error) else: if post.poster_id or post.poster_name != posts[0].poster_name: raise serializers.ValidationError(authorship_error) if posts[0].pk != thread.first_post_id: if (posts[0].is_hidden != post.is_hidden or posts[0].is_unapproved != post.is_unapproved): raise serializers.ValidationError( _("Posts with different visibility can't be merged.") ) posts.append(post) if len(posts) != len(data): raise serializers.ValidationError(_("One or more posts to merge could not be found.")) self.posts_cache = posts return data
def clean_posts_for_merge(request, thread): try: posts_ids = list(map(int, request.data.get('posts', []))) except (ValueError, TypeError): raise PermissionDenied( _("One or more post ids received were invalid.")) if len(posts_ids) < 2: raise PermissionDenied( _("You have to select at least two posts to merge.")) elif len(posts_ids) > MERGE_LIMIT: message = ungettext( "No more than %(limit)s post can be merged at single time.", "No more than %(limit)s posts can be merged at single time.", MERGE_LIMIT, ) raise PermissionDenied(message % {'limit': MERGE_LIMIT}) posts_queryset = exclude_invisible_posts(request.user, thread.category, thread.post_set) posts_queryset = posts_queryset.filter(id__in=posts_ids).order_by('id') posts = [] for post in posts_queryset: post.category = thread.category post.thread = thread allow_merge_post(request.user, post) if not posts: posts.append(post) else: authorship_error = _( "Posts made by different users can't be merged.") if posts[0].poster_id: if post.poster_id != posts[0].poster_id: raise PermissionDenied(authorship_error) else: if post.poster_id or post.poster_name != posts[0].poster_name: raise PermissionDenied(authorship_error) if posts[0].pk != thread.first_post_id: if (posts[0].is_hidden != post.is_hidden or posts[0].is_unapproved != post.is_unapproved): raise PermissionDenied( _("Posts with different visibility can't be merged.")) posts.append(post) if len(posts) != len(posts_ids): raise PermissionDenied( _("One or more posts to merge could not be found.")) return posts
def get_events_queryset(self, request, thread, limit, first_post=None, last_post=None): queryset = thread.post_set.select_related( 'category', 'poster', 'poster__rank', 'poster__ban_cache', 'poster__online_tracker', ).filter(is_event=True) if first_post: queryset = queryset.filter(pk__gt=first_post.pk) if last_post: queryset = queryset.filter(pk__lt=last_post.pk) queryset = exclude_invisible_posts(request.user, thread.category, queryset) return list(queryset.order_by('-id')[:limit])
def clean_posts_for_patch(request, thread, posts_ids): posts_queryset = exclude_invisible_posts(request.user, thread.category, thread.post_set) posts_queryset = posts_queryset.filter( id__in=posts_ids, is_event=False, ).order_by('id') posts = [] for post in posts_queryset: post.category = thread.category post.thread = thread posts.append(post) if len(posts) != len(posts_ids): raise PermissionDenied(_("One or more posts to update could not be found.")) return posts
def clean_posts_for_split(request, thread): try: posts_ids = list(map(int, request.data.get('posts', []))) except (ValueError, TypeError): raise SplitError(_("One or more post ids received were invalid.")) if not posts_ids: raise SplitError(_("You have to specify at least one post to split.")) elif len(posts_ids) > SPLIT_LIMIT: message = ungettext( "No more than %(limit)s post can be split at single time.", "No more than %(limit)s posts can be split at single time.", SPLIT_LIMIT, ) raise SplitError(message % {'limit': SPLIT_LIMIT}) posts_queryset = exclude_invisible_posts(request.user, thread.category, thread.post_set) posts_queryset = posts_queryset.select_for_update().filter( id__in=posts_ids).order_by('id') posts = [] for post in posts_queryset: if post.is_event: raise SplitError(_("Events can't be split.")) if post.pk == thread.first_post_id: raise SplitError(_("You can't split thread's first post.")) if post.is_hidden and not thread.category.acl['can_hide_posts']: raise SplitError( _("You can't split posts the content you can't see.")) posts.append(post) if len(posts) != len(posts_ids): raise SplitError(_("One or more posts to split could not be found.")) return posts
def clean_posts_for_delete(request, thread): try: posts_ids = list(map(int, request.data or [])) except (ValueError, TypeError): raise PermissionDenied( _("One or more post ids received were invalid.")) if not posts_ids: raise PermissionDenied( _("You have to specify at least one post to delete.")) elif len(posts_ids) > DELETE_LIMIT: message = ungettext( "No more than %(limit)s post can be deleted at single time.", "No more than %(limit)s posts can be deleted at single time.", DELETE_LIMIT, ) raise PermissionDenied(message % {'limit': DELETE_LIMIT}) posts_queryset = exclude_invisible_posts(request.user, thread.category, thread.post_set) posts_queryset = posts_queryset.filter(id__in=posts_ids).order_by('id') posts = [] for post in posts_queryset: post.thread = thread if post.is_event: allow_delete_event(request.user, post) else: allow_delete_post(request.user, post) posts.append(post) if len(posts) != len(posts_ids): raise PermissionDenied( _("One or more posts to delete could not be found.")) return posts
def get_queryset(self, request, thread): return exclude_invisible_posts(request.user, thread.category, thread.post_set)
def posts_queryset(user, thread): qs = exclude_invisible_posts(thread.post_set, user, thread.forum) return qs.count(), qs.order_by('id')
def exclude_invisible_posts(self, queryset, user, forum, thread): return exclude_invisible_posts(queryset, user, forum)
def exclude_invisible_posts(self, queryset, user, forum, thread): return exclude_invisible_posts(queryset, user, forum)
def posts_queryset(user, thread): qs = exclude_invisible_posts(thread.post_set, user, thread.forum) return qs.count(), qs.order_by('id')
def get_queryset(self, request, thread): return exclude_invisible_posts(request.user, thread.category, thread.post_set)