import time import random import os import os.path import logging import urlparse import comment_client as cc from django.core import exceptions from django.contrib.auth.decorators import login_required from django.views.decorators.http import require_POST, require_GET from django.views.decorators import csrf from django.core.files.storage import get_storage_class from django.utils.translation import ugettext as _ from django.conf import settings from mitxmako.shortcuts import render_to_response, render_to_string from django_comment_client.utils import JsonResponse, JsonError, extract import django_comment_client.utils as utils from django_comment_client.permissions import check_permissions_by_view import functools def permitted(fn): @functools.wraps(fn) def wrapper(request, *args, **kwargs): def fetch_content(): if "thread_id" in kwargs: content = cc.Thread.find(kwargs["thread_id"]).to_dict() elif "comment_id" in kwargs: content = cc.Comment.find(kwargs["comment_id"]).to_dict() else: content = None return content if check_permissions_by_view(request.user, kwargs['course_id'], fetch_content(), request.view_name): return fn(request, *args, **kwargs) else: return JsonError("unauthorized") return wrapper @require_POST @login_required @permitted def create_thread(request, course_id, commentable_id): post = request.POST thread = cc.Thread(**extract(post, ['body', 'title', 'tags'])) thread.anonymous = post.get('anonymous', 'false').lower() == 'true' thread.commentable_id = commentable_id thread.course_id = course_id thread.user_id = request.user.id thread.save() if post.get('auto_subscribe', 'false').lower() == 'true': user = cc.User.from_django_user(request.user) user.follow(thread) if request.is_ajax(): context = { 'course_id': course_id, 'thread': thread.to_dict(), } html = render_to_string('discussion/ajax_create_thread.html', context) annotated_content_info = utils.get_annotated_content_info(course_id, thread.to_dict(), request.user, 'thread') return JsonResponse({ 'html': html, 'content': thread.to_dict(), 'annotated_content_info': annotated_content_info, }) else: return JsonResponse(thread.to_dict()) @require_POST @login_required @permitted def update_thread(request, course_id, thread_id): thread = cc.Thread.find(thread_id) thread.update_attributes(**extract(request.POST, ['body', 'title', 'tags'])) thread.save() if request.is_ajax(): context = { 'thread': thread.to_dict(), 'course_id': course_id, } html = render_to_string('discussion/ajax_update_thread.html', context) annotated_content_info = utils.get_annotated_content_info(course_id, thread.to_dict(), request.user, 'thread') return JsonResponse({ 'html': html, 'content': thread.to_dict(), 'annotated_content_info': annotated_content_info, }) else: return JsonResponse(thread.to_dict()) def _create_comment(request, course_id, thread_id=None, parent_id=None): post = request.POST comment = cc.Comment(**extract(post, ['body'])) comment.anonymous = post.get('anonymous', 'false').lower() == 'true' comment.user_id = request.user.id comment.course_id = course_id comment.thread_id = thread_id comment.parent_id = parent_id comment.save() dict_comment = comment.to_dict() if post.get('auto_subscribe', 'false').lower() == 'true': user = cc.User.from_django_user(request.user) user.follow(comment.thread) if request.is_ajax(): context = { 'comment': comment.to_dict(), } html = render_to_string('discussion/ajax_create_comment.html', context) annotated_content_info = utils.get_annotated_content_info(course_id, comment.to_dict(), request.user, 'comment') return JsonResponse({ 'html': html, 'content': comment.to_dict(), 'annotated_content_info': annotated_content_info, }) else: return JsonResponse(comment.to_dict()) @require_POST @login_required @permitted def create_comment(request, course_id, thread_id): return _create_comment(request, course_id, thread_id=thread_id) @require_POST @login_required @permitted def delete_thread(request, course_id, thread_id): thread = cc.Thread.find(thread_id) thread.delete() return JsonResponse(thread.to_dict()) @require_POST @login_required @permitted def update_comment(request, course_id, comment_id): comment = cc.Comment.find(comment_id) comment.update_attributes(**extract(request.POST, ['body'])) comment.save() if request.is_ajax(): context = { 'comment': comment.to_dict(), 'course_id': course_id, } html = render_to_string('discussion/ajax_update_comment.html', context) annotated_content_info = utils.get_annotated_content_info(course_id, comment.to_dict(), request.user, 'comment') return JsonResponse({ 'html': html, 'content': comment.to_dict(), 'annotated_content_info': annotated_content_info, }) else: return JsonResponse(comment.to_dict()), @require_POST @login_required @permitted def endorse_comment(request, course_id, comment_id): comment = cc.Comment.find(comment_id) comment.endorsed = request.POST.get('endorsed', 'false').lower() == 'true' comment.save() return JsonResponse(comment.to_dict()) @require_POST @login_required @permitted def openclose_thread(request, course_id, thread_id): comment = cc.Comment.find(comment_id) comment.endorsed = request.POST.get('closed', 'false').lower() == 'true' comment.save() return JsonResponse(comment.to_dict()) @require_POST @login_required @permitted def create_sub_comment(request, course_id, comment_id): return _create_comment(request, course_id, parent_id=comment_id) @require_POST @login_required @permitted def delete_comment(request, course_id, comment_id): comment = cc.Comment.find(comment_id) comment.delete() return JsonResponse(comment.to_dict()) @require_POST @login_required @permitted def vote_for_comment(request, course_id, comment_id, value): user = cc.User.from_django_user(request.user) comment = cc.Comment.find(comment_id) user.vote(comment, value) return JsonResponse(comment.to_dict()) @require_POST @login_required @permitted def undo_vote_for_comment(request, course_id, comment_id): user = cc.User.from_django_user(request.user) comment = cc.Comment.find(comment_id) user.unvote(comment) return JsonResponse(comment.to_dict()) @require_POST @login_required @permitted def vote_for_thread(request, course_id, thread_id, value): user = cc.User.from_django_user(request.user) thread = cc.Thread.find(thread_id) user.vote(thread, value) return JsonResponse(thread.to_dict()) @require_POST @login_required @permitted def undo_vote_for_thread(request, course_id, thread_id): user = cc.User.from_django_user(request.user) thread = cc.Thread.find(thread_id) user.unvote(thread) return JsonResponse(thread.to_dict()) @require_POST @login_required @permitted def follow_thread(request, course_id, thread_id): user = cc.User.from_django_user(request.user) thread = cc.Thread.find(thread_id) user.follow(thread) return JsonResponse({}) @require_POST @login_required @permitted def follow_commentable(request, course_id, commentable_id): user = cc.User.from_django_user(request.user) commentable = cc.Commentable.find(commentable_id) user.follow(commentable) return JsonResponse({}) @require_POST @login_required @permitted def follow_user(request, course_id, followed_user_id): user = cc.User.from_django_user(request.user) followed_user = cc.User.find(followed_user_id) user.follow(followed_user) return JsonResponse({}) @require_POST @login_required @permitted def unfollow_thread(request, course_id, thread_id): user = cc.User.from_django_user(request.user) thread = cc.Thread.find(thread_id) user.unfollow(thread) return JsonResponse({}) @require_POST @login_required @permitted def unfollow_commentable(request, course_id, commentable_id): user = cc.User.from_django_user(request.user) commentable = cc.Commentable.find(commentable_id) user.unfollow(commentable) return JsonResponse({}) @require_POST @login_required @permitted def unfollow_user(request, course_id, followed_user_id): user = cc.User.from_django_user(request.user) followed_user = cc.User.find(followed_user_id) user.unfollow(followed_user) return JsonResponse({}) @require_GET def search_similar_threads(request, course_id, commentable_id): text = request.GET.get('text', None) if text: return JsonResponse( cc.search_similar_threads( course_id, recursive=False, query_params={ 'text': text, 'commentable_id': commentable_id, }, )) else: return JsonResponse([]) @require_GET def tags_autocomplete(request, course_id): value = request.GET.get('q', None) results = [] if value: results = cc.tags_autocomplete(value) return JsonResponse(results) @require_POST @login_required @csrf.csrf_exempt def upload(request, course_id):#ajax upload file to a question or answer """view that handles file upload via Ajax """ # check upload permission result = '' error = '' new_file_name = '' try: # TODO authorization #may raise exceptions.PermissionDenied #if request.user.is_anonymous(): # msg = _('Sorry, anonymous users cannot upload files') # raise exceptions.PermissionDenied(msg) #request.user.assert_can_upload_file() # check file type f = request.FILES['file-upload'] file_extension = os.path.splitext(f.name)[1].lower() if not file_extension in settings.DISCUSSION_ALLOWED_UPLOAD_FILE_TYPES: file_types = "', '".join(settings.DISCUSSION_ALLOWED_UPLOAD_FILE_TYPES) msg = _("allowed file types are '%(file_types)s'") % \ {'file_types': file_types} raise exceptions.PermissionDenied(msg) # generate new file name new_file_name = str( time.time() ).replace( '.', str(random.randint(0,100000)) ) + file_extension file_storage = get_storage_class()() # use default storage to store file file_storage.save(new_file_name, f) # check file size # byte size = file_storage.size(new_file_name) if size > settings.ASKBOT_MAX_UPLOAD_FILE_SIZE: file_storage.delete(new_file_name) msg = _("maximum upload file size is %(file_size)sK") % \ {'file_size': settings.ASKBOT_MAX_UPLOAD_FILE_SIZE} raise exceptions.PermissionDenied(msg) except exceptions.PermissionDenied, e: error = unicode(e) except Exception, e: logging.critical(unicode(e)) error = _('Error uploading file. Please contact the site administrator. Thank you.') if error == '': result = 'Good' file_url = file_storage.url(new_file_name) parsed_url = urlparse.urlparse(file_url) file_url = urlparse.urlunparse( urlparse.ParseResult( parsed_url.scheme, parsed_url.netloc, parsed_url.path, '', '', '' ) ) else: result = '' file_url = '' return JsonResponse({ 'result': { 'msg': result, 'error': error, 'file_url': file_url, } })