Mercurial > public > sg101
comparison gpp/forums/views/main.py @ 459:9d3bd7304050
Fixing #221. Also combined all permissions checks into a new module, permissions.py. This allows us to cache user, category, and forum groups information since it rarely changes.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Sat, 02 Jul 2011 23:35:45 +0000 |
parents | 72ef6e809f79 |
children | 2ff5f4c1476d |
comparison
equal
deleted
inserted
replaced
458:9a4bffdf37c3 | 459:9d3bd7304050 |
---|---|
19 from django.template import RequestContext | 19 from django.template import RequestContext |
20 from django.views.decorators.http import require_POST | 20 from django.views.decorators.http import require_POST |
21 from django.utils.text import wrap | 21 from django.utils.text import wrap |
22 from django.db.models import F | 22 from django.db.models import F |
23 | 23 |
24 import antispam | |
25 import antispam.utils | |
26 from bio.models import UserProfile, BadgeOwnership | |
24 from core.paginator import DiggPaginator | 27 from core.paginator import DiggPaginator |
25 from core.functions import email_admins | 28 from core.functions import email_admins |
26 from forums.models import Forum, Topic, Post, FlaggedPost, TopicLastVisit, \ | 29 |
27 ForumLastVisit, Attachment | 30 from forums.models import (Forum, Topic, Post, FlaggedPost, TopicLastVisit, |
28 from forums.forms import NewTopicForm, NewPostForm, PostForm, MoveTopicForm, \ | 31 ForumLastVisit, Attachment) |
29 SplitTopicForm | 32 from forums.forms import (NewTopicForm, NewPostForm, PostForm, MoveTopicForm, |
30 from forums.unread import get_forum_unread_status, get_topic_unread_status, \ | 33 SplitTopicForm) |
31 get_post_unread_status, get_unread_topics | 34 from forums.unread import (get_forum_unread_status, get_topic_unread_status, |
32 | 35 get_post_unread_status, get_unread_topics) |
33 from bio.models import UserProfile, BadgeOwnership | 36 |
34 import antispam | |
35 import antispam.utils | |
36 from forums.attachments import AttachmentProcessor | 37 from forums.attachments import AttachmentProcessor |
38 import forums.permissions as perms | |
37 | 39 |
38 ####################################################################### | 40 ####################################################################### |
39 | 41 |
40 TOPICS_PER_PAGE = 50 | 42 TOPICS_PER_PAGE = 50 |
41 POSTS_PER_PAGE = 20 | 43 POSTS_PER_PAGE = 20 |
115 """ | 117 """ |
116 Displays all the topics in a forum. | 118 Displays all the topics in a forum. |
117 """ | 119 """ |
118 forum = get_object_or_404(Forum.objects.select_related(), slug=slug) | 120 forum = get_object_or_404(Forum.objects.select_related(), slug=slug) |
119 | 121 |
120 if not forum.category.can_access(request.user): | 122 if not perms.can_access(forum.category, request.user): |
121 return HttpResponseForbidden() | 123 return HttpResponseForbidden() |
122 | 124 |
123 feed = None | 125 feed = None |
124 if not forum.category.groups.all(): | 126 if not forum.category.groups.all(): |
125 feed = { | 127 feed = { |
139 attach_topic_page_ranges(page.object_list) | 141 attach_topic_page_ranges(page.object_list) |
140 | 142 |
141 # we do this for the template since it is rendered twice | 143 # we do this for the template since it is rendered twice |
142 page_nav = render_to_string('forums/pagination.html', {'page': page}) | 144 page_nav = render_to_string('forums/pagination.html', {'page': page}) |
143 | 145 |
144 can_moderate = _can_moderate(forum, request.user) | 146 can_moderate = perms.can_moderate(forum, request.user) |
145 | 147 |
146 return render_to_response('forums/forum_index.html', { | 148 return render_to_response('forums/forum_index.html', { |
147 'forum': forum, | 149 'forum': forum, |
148 'feed': feed, | 150 'feed': feed, |
149 'page': page, | 151 'page': page, |
158 Displays all the posts in a topic. | 160 Displays all the posts in a topic. |
159 """ | 161 """ |
160 topic = get_object_or_404(Topic.objects.select_related( | 162 topic = get_object_or_404(Topic.objects.select_related( |
161 'forum', 'forum__category', 'last_post'), pk=id) | 163 'forum', 'forum__category', 'last_post'), pk=id) |
162 | 164 |
163 if not topic.forum.category.can_access(request.user): | 165 if not perms.can_access(topic.forum.category, request.user): |
164 return HttpResponseForbidden() | 166 return HttpResponseForbidden() |
165 | 167 |
166 topic.view_count = F('view_count') + 1 | 168 topic.view_count = F('view_count') + 1 |
167 topic.save(force_update=True) | 169 topic.save(force_update=True) |
168 | 170 |
220 _update_last_visit(request.user, topic, visit_time) | 222 _update_last_visit(request.user, topic, visit_time) |
221 | 223 |
222 # we do this for the template since it is rendered twice | 224 # we do this for the template since it is rendered twice |
223 page_nav = render_to_string('forums/pagination.html', {'page': page}) | 225 page_nav = render_to_string('forums/pagination.html', {'page': page}) |
224 | 226 |
225 can_moderate = _can_moderate(topic.forum, request.user) | 227 can_moderate = perms.can_moderate(topic.forum, request.user) |
226 | 228 |
227 can_reply = request.user.is_authenticated() and ( | 229 can_reply = request.user.is_authenticated() and ( |
228 not topic.locked or can_moderate) | 230 not topic.locked or can_moderate) |
229 | 231 |
230 is_favorite = request.user.is_authenticated() and ( | 232 is_favorite = request.user.is_authenticated() and ( |
287 """ | 289 """ |
288 This view handles the creation of new topics. | 290 This view handles the creation of new topics. |
289 """ | 291 """ |
290 forum = get_object_or_404(Forum.objects.select_related(), slug=slug) | 292 forum = get_object_or_404(Forum.objects.select_related(), slug=slug) |
291 | 293 |
292 if not forum.category.can_access(request.user): | 294 if not perms.can_access(forum.category, request.user): |
293 return HttpResponseForbidden() | 295 return HttpResponseForbidden() |
294 | 296 |
295 if request.method == 'POST': | 297 if request.method == 'POST': |
296 form = NewTopicForm(request.user, forum, request.POST) | 298 form = NewTopicForm(request.user, forum, request.POST) |
297 if form.is_valid(): | 299 if form.is_valid(): |
336 if not request.user.is_authenticated(): | 338 if not request.user.is_authenticated(): |
337 return HttpResponseForbidden('Please login or register to post.') | 339 return HttpResponseForbidden('Please login or register to post.') |
338 | 340 |
339 form = NewPostForm(request.POST) | 341 form = NewPostForm(request.POST) |
340 if form.is_valid(): | 342 if form.is_valid(): |
341 if not _can_post_in_topic(form.topic, request.user): | 343 if not perms.can_post(form.topic, request.user): |
342 return HttpResponseForbidden("You don't have permission to post in this topic.") | 344 return HttpResponseForbidden("You don't have permission to post in this topic.") |
343 if antispam.utils.spam_check(request, form.cleaned_data['body']): | 345 if antispam.utils.spam_check(request, form.cleaned_data['body']): |
344 return HttpResponseForbidden(antispam.BUSTED_MESSAGE) | 346 return HttpResponseForbidden(antispam.BUSTED_MESSAGE) |
345 | 347 |
346 post = form.save(request.user, request.META.get("REMOTE_ADDR", "")) | 348 post = form.save(request.user, request.META.get("REMOTE_ADDR", "")) |
350 _bump_post_count(request.user) | 352 _bump_post_count(request.user) |
351 _update_last_visit(request.user, form.topic, datetime.datetime.now()) | 353 _update_last_visit(request.user, form.topic, datetime.datetime.now()) |
352 | 354 |
353 return render_to_response('forums/display_post.html', { | 355 return render_to_response('forums/display_post.html', { |
354 'post': post, | 356 'post': post, |
355 'can_moderate': _can_moderate(form.topic.forum, request.user), | 357 'can_moderate': perms.can_moderate(form.topic.forum, request.user), |
356 'can_reply': True, | 358 'can_reply': True, |
357 }, | 359 }, |
358 context_instance=RequestContext(request)) | 360 context_instance=RequestContext(request)) |
359 | 361 |
360 return HttpResponseBadRequest("Oops, did you forget some text?"); | 362 return HttpResponseBadRequest("Oops, did you forget some text?"); |
417 This view function allows authorized users to edit posts. | 419 This view function allows authorized users to edit posts. |
418 The superuser, forum moderators, and original author can edit posts. | 420 The superuser, forum moderators, and original author can edit posts. |
419 """ | 421 """ |
420 post = get_object_or_404(Post.objects.select_related(), pk=id) | 422 post = get_object_or_404(Post.objects.select_related(), pk=id) |
421 | 423 |
422 can_moderate = _can_moderate(post.topic.forum, request.user) | 424 can_moderate = perms.can_moderate(post.topic.forum, request.user) |
423 can_edit = can_moderate or request.user == post.user | 425 can_edit = can_moderate or request.user == post.user |
424 | 426 |
425 if not can_edit: | 427 if not can_edit: |
426 return HttpResponseForbidden("You don't have permission to edit that post.") | 428 return HttpResponseForbidden("You don't have permission to edit that post.") |
427 | 429 |
576 """ | 578 """ |
577 This function is the view for creating a normal, non-quick reply | 579 This function is the view for creating a normal, non-quick reply |
578 to a topic. | 580 to a topic. |
579 """ | 581 """ |
580 topic = get_object_or_404(Topic.objects.select_related(), pk=topic_id) | 582 topic = get_object_or_404(Topic.objects.select_related(), pk=topic_id) |
581 can_post = _can_post_in_topic(topic, request.user) | 583 can_post = perms.can_post(topic, request.user) |
582 | 584 |
583 if can_post: | 585 if can_post: |
584 if request.method == 'POST': | 586 if request.method == 'POST': |
585 form = PostForm(request.POST) | 587 form = PostForm(request.POST) |
586 if form.is_valid(): | 588 if form.is_valid(): |
623 def mod_topic_stick(request, id): | 625 def mod_topic_stick(request, id): |
624 """ | 626 """ |
625 This view function is for moderators to toggle the sticky status of a topic. | 627 This view function is for moderators to toggle the sticky status of a topic. |
626 """ | 628 """ |
627 topic = get_object_or_404(Topic.objects.select_related(), pk=id) | 629 topic = get_object_or_404(Topic.objects.select_related(), pk=id) |
628 if _can_moderate(topic.forum, request.user): | 630 if perms.can_moderate(topic.forum, request.user): |
629 topic.sticky = not topic.sticky | 631 topic.sticky = not topic.sticky |
630 topic.save() | 632 topic.save() |
631 return HttpResponseRedirect(topic.get_absolute_url()) | 633 return HttpResponseRedirect(topic.get_absolute_url()) |
632 | 634 |
633 return HttpResponseForbidden() | 635 return HttpResponseForbidden() |
637 def mod_topic_lock(request, id): | 639 def mod_topic_lock(request, id): |
638 """ | 640 """ |
639 This view function is for moderators to toggle the locked status of a topic. | 641 This view function is for moderators to toggle the locked status of a topic. |
640 """ | 642 """ |
641 topic = get_object_or_404(Topic.objects.select_related(), pk=id) | 643 topic = get_object_or_404(Topic.objects.select_related(), pk=id) |
642 if _can_moderate(topic.forum, request.user): | 644 if perms.can_moderate(topic.forum, request.user): |
643 topic.locked = not topic.locked | 645 topic.locked = not topic.locked |
644 topic.save() | 646 topic.save() |
645 return HttpResponseRedirect(topic.get_absolute_url()) | 647 return HttpResponseRedirect(topic.get_absolute_url()) |
646 | 648 |
647 return HttpResponseForbidden() | 649 return HttpResponseForbidden() |
651 def mod_topic_delete(request, id): | 653 def mod_topic_delete(request, id): |
652 """ | 654 """ |
653 This view function is for moderators to delete an entire topic. | 655 This view function is for moderators to delete an entire topic. |
654 """ | 656 """ |
655 topic = get_object_or_404(Topic.objects.select_related(), pk=id) | 657 topic = get_object_or_404(Topic.objects.select_related(), pk=id) |
656 if _can_moderate(topic.forum, request.user): | 658 if perms.can_moderate(topic.forum, request.user): |
657 forum_url = topic.forum.get_absolute_url() | 659 forum_url = topic.forum.get_absolute_url() |
658 _delete_topic(topic) | 660 _delete_topic(topic) |
659 return HttpResponseRedirect(forum_url) | 661 return HttpResponseRedirect(forum_url) |
660 | 662 |
661 return HttpResponseForbidden() | 663 return HttpResponseForbidden() |
665 def mod_topic_move(request, id): | 667 def mod_topic_move(request, id): |
666 """ | 668 """ |
667 This view function is for moderators to move a topic to a different forum. | 669 This view function is for moderators to move a topic to a different forum. |
668 """ | 670 """ |
669 topic = get_object_or_404(Topic.objects.select_related(), pk=id) | 671 topic = get_object_or_404(Topic.objects.select_related(), pk=id) |
670 if not _can_moderate(topic.forum, request.user): | 672 if not perms.can_moderate(topic.forum, request.user): |
671 return HttpResponseForbidden() | 673 return HttpResponseForbidden() |
672 | 674 |
673 if request.method == 'POST': | 675 if request.method == 'POST': |
674 form = MoveTopicForm(request.user, request.POST) | 676 form = MoveTopicForm(request.user, request.POST) |
675 if form.is_valid(): | 677 if form.is_valid(): |
694 Displays a view to allow moderators to perform various operations | 696 Displays a view to allow moderators to perform various operations |
695 on topics in a forum in bulk. We currently support mass locking/unlocking, | 697 on topics in a forum in bulk. We currently support mass locking/unlocking, |
696 stickying and unstickying, moving, and deleting topics. | 698 stickying and unstickying, moving, and deleting topics. |
697 """ | 699 """ |
698 forum = get_object_or_404(Forum.objects.select_related(), slug=slug) | 700 forum = get_object_or_404(Forum.objects.select_related(), slug=slug) |
699 if not _can_moderate(forum, request.user): | 701 if not perms.can_moderate(forum, request.user): |
700 return HttpResponseForbidden() | 702 return HttpResponseForbidden() |
701 | 703 |
702 topics = forum.topics.select_related('user', 'last_post', 'last_post__user') | 704 topics = forum.topics.select_related('user', 'last_post', 'last_post__user') |
703 paginator = create_topic_paginator(topics) | 705 paginator = create_topic_paginator(topics) |
704 page_num = get_page_num(request) | 706 page_num = get_page_num(request) |
768 """ | 770 """ |
769 This view marks all the topics in the forum as being read. | 771 This view marks all the topics in the forum as being read. |
770 """ | 772 """ |
771 forum = get_object_or_404(Forum.objects.select_related(), slug=slug) | 773 forum = get_object_or_404(Forum.objects.select_related(), slug=slug) |
772 | 774 |
773 if not forum.category.can_access(request.user): | 775 if not perms.can_access(forum.category, request.user): |
774 return HttpResponseForbidden() | 776 return HttpResponseForbidden() |
775 | 777 |
776 forum.catchup(request.user) | 778 forum.catchup(request.user) |
777 return HttpResponseRedirect(forum.get_absolute_url()) | 779 return HttpResponseRedirect(forum.get_absolute_url()) |
778 | 780 |
781 def mod_topic_split(request, id): | 783 def mod_topic_split(request, id): |
782 """ | 784 """ |
783 This view function allows moderators to split posts off to a new topic. | 785 This view function allows moderators to split posts off to a new topic. |
784 """ | 786 """ |
785 topic = get_object_or_404(Topic.objects.select_related(), pk=id) | 787 topic = get_object_or_404(Topic.objects.select_related(), pk=id) |
786 if not _can_moderate(topic.forum, request.user): | 788 if not perms.can_moderate(topic.forum, request.user): |
787 return HttpResponseRedirect(topic.get_absolute_url()) | 789 return HttpResponseRedirect(topic.get_absolute_url()) |
788 | 790 |
789 if request.method == "POST": | 791 if request.method == "POST": |
790 form = SplitTopicForm(request.user, request.POST) | 792 form = SplitTopicForm(request.user, request.POST) |
791 if form.is_valid(): | 793 if form.is_valid(): |
928 @login_required | 930 @login_required |
929 def post_ip_info(request, post_id): | 931 def post_ip_info(request, post_id): |
930 """Displays information about the IP address the post was made from.""" | 932 """Displays information about the IP address the post was made from.""" |
931 post = get_object_or_404(Post.objects.select_related(), pk=post_id) | 933 post = get_object_or_404(Post.objects.select_related(), pk=post_id) |
932 | 934 |
933 if not _can_moderate(post.topic.forum, request.user): | 935 if not perms.can_moderate(post.topic.forum, request.user): |
934 return HttpResponseForbidden("You don't have permission for this post.") | 936 return HttpResponseForbidden("You don't have permission for this post.") |
935 | 937 |
936 ip_users = sorted(set(Post.objects.filter( | 938 ip_users = sorted(set(Post.objects.filter( |
937 user_ip=post.user_ip).values_list('user__username', flat=True))) | 939 user_ip=post.user_ip).values_list('user__username', flat=True))) |
938 | 940 |
967 'title': page_title, | 969 'title': page_title, |
968 'page': page, | 970 'page': page, |
969 'page_nav': page_nav, | 971 'page_nav': page_nav, |
970 }, | 972 }, |
971 context_instance=RequestContext(request)) | 973 context_instance=RequestContext(request)) |
972 | |
973 | |
974 def _can_moderate(forum, user): | |
975 """ | |
976 Determines if a user has permission to moderate a given forum. | |
977 """ | |
978 return user.is_authenticated() and ( | |
979 user.is_superuser or user in forum.moderators.all()) | |
980 | |
981 | |
982 def _can_post_in_topic(topic, user): | |
983 """ | |
984 This function returns true if the given user can post in the given topic | |
985 and false otherwise. | |
986 """ | |
987 return (not topic.locked and topic.forum.category.can_access(user)) or \ | |
988 (user.is_superuser or user in topic.forum.moderators.all()) | |
989 | 974 |
990 | 975 |
991 def _bump_post_count(user): | 976 def _bump_post_count(user): |
992 """ | 977 """ |
993 Increments the forum_post_count for the given user. | 978 Increments the forum_post_count for the given user. |