def upload_async(request, media_type='image'): """Upload images or videos from request.FILES.""" # TODO(paul): validate the Submit File on upload modal async # even better, use JS validation for title length. try: if media_type == 'image': file_info = upload_image(request) else: file_info = upload_video(request) except FileTooLargeError as e: return HttpResponseBadRequest( json.dumps({ 'status': 'error', 'message': e.args[0] })) if isinstance(file_info, dict) and 'thumbnail_url' in file_info: schedule_rebuild_kb() return HttpResponse( json.dumps({ 'status': 'success', 'file': file_info })) message = MSG_FAIL_UPLOAD[media_type] return HttpResponseBadRequest( json.dumps({ 'status': 'error', 'message': unicode(message), 'errors': file_info }))
def review_revision(request, document_slug, revision_id): """Review a revision of a wiki document.""" rev = get_object_or_404(Revision, pk=revision_id, document__slug=document_slug) doc = rev.document form = ReviewForm() if request.method == 'POST': form = ReviewForm(request.POST) if form.is_valid() and not rev.reviewed: # Don't allow revisions to be reviewed twice rev.is_approved = 'approve' in request.POST rev.reviewer = request.user rev.reviewed = datetime.now() if form.cleaned_data['significance']: rev.significance = form.cleaned_data['significance'] rev.save() # Send an email (not really a "notification" in the sense that # there's a Watch table entry) to revision creator. msg = form.cleaned_data['comment'] send_reviewed_notification.delay(rev, doc, msg) # If approved, send approved notification ApproveRevisionInLocaleEvent(rev).fire(exclude=rev.creator) # Schedule KB rebuild? schedule_rebuild_kb() return HttpResponseRedirect( reverse('wiki.document_revisions', args=[document_slug])) if doc.parent: # A translation parent_revision = get_current_or_latest_revision(doc.parent) template = 'wiki/review_translation.html' else: parent_revision = None template = 'wiki/review_revision.html' data = { 'revision': rev, 'document': doc, 'form': form, 'parent_revision': parent_revision } data.update(SHOWFOR_DATA) return jingo.render(request, template, data)
def review_revision(request, document_slug, revision_id): """Review a revision of a wiki document.""" rev = get_object_or_404(Revision, pk=revision_id, document__slug=document_slug) doc = rev.document form = ReviewForm() # Don't ask significance if this doc is a translation or if it has no # former approved versions: should_ask_significance = not doc.parent and doc.current_revision if request.method == 'POST': form = ReviewForm(request.POST) if form.is_valid() and not rev.reviewed: # Don't allow revisions to be reviewed twice rev.is_approved = 'approve' in request.POST rev.reviewer = request.user rev.reviewed = datetime.now() if should_ask_significance and form.cleaned_data['significance']: rev.significance = form.cleaned_data['significance'] rev.save() # Send an email (not really a "notification" in the sense that # there's a Watch table entry) to revision creator. msg = form.cleaned_data['comment'] send_reviewed_notification.delay(rev, doc, msg) # If approved, send approved notification ApproveRevisionInLocaleEvent(rev).fire(exclude=rev.creator) # Schedule KB rebuild? schedule_rebuild_kb() return HttpResponseRedirect(reverse('wiki.document_revisions', args=[document_slug])) if doc.parent: # A translation parent_revision = get_current_or_latest_revision(doc.parent) template = 'wiki/review_translation.html' else: parent_revision = None template = 'wiki/review_revision.html' data = {'revision': rev, 'document': doc, 'form': form, 'parent_revision': parent_revision, 'should_ask_significance': should_ask_significance} data.update(SHOWFOR_DATA) return jingo.render(request, template, data)
def upload_async(request, media_type="image"): """Upload images or videos from request.FILES.""" # TODO(paul): validate the Submit File on upload modal async # even better, use JS validation for title length. try: if media_type == "image": file_info = upload_image(request) else: file_info = upload_video(request) except FileTooLargeError as e: return HttpResponseBadRequest(json.dumps({"status": "error", "message": e.args[0]})) if isinstance(file_info, dict) and "thumbnail_url" in file_info: schedule_rebuild_kb() return HttpResponse(json.dumps({"status": "success", "file": file_info})) message = MSG_FAIL_UPLOAD[media_type] return HttpResponseBadRequest(json.dumps({"status": "error", "message": unicode(message), "errors": file_info}))
def delete_media(request, media_id, media_type='image'): """Delete media and redirect to gallery view.""" media, media_format = _get_media_info(media_id, media_type) check_media_permissions(media, request.user, 'delete') if request.method == 'GET': # Render the confirmation page return jingo.render(request, 'gallery/confirm_media_delete.html', {'media': media, 'media_type': media_type, 'media_format': media_format}) # Handle confirm delete form POST log.warning('User %s is deleting %s with id=%s' % (request.user, media_type, media.id)) media.delete() # Rebuild KB schedule_rebuild_kb() return HttpResponseRedirect(reverse('gallery.gallery', args=[media_type]))
def delete_media(request, media_id, media_type="image"): """Delete media and redirect to gallery view.""" media, media_format = _get_media_info(media_id, media_type) check_media_permissions(media, request.user, "delete") if request.method == "GET": # Render the confirmation page return jingo.render( request, "gallery/confirm_media_delete.html", {"media": media, "media_type": media_type, "media_format": media_format}, ) # Handle confirm delete form POST log.warning("User %s is deleting %s with id=%s" % (request.user, media_type, media.id)) media.delete() # Rebuild KB schedule_rebuild_kb() return HttpResponseRedirect(reverse("gallery.gallery", args=[media_type]))
def upload(request, media_type='image'): """Finalizes an uploaded draft.""" drafts = _get_drafts(request.user) if media_type == 'image' and drafts['image']: # We're publishing an image draft! image_form = _init_media_form(ImageForm, request, drafts['image'][0]) if image_form.is_valid(): img = image_form.save(is_draft=None) generate_thumbnail.delay(img, 'file', 'thumbnail') compress_image.delay(img, 'file') # TODO: We can drop this when we start using Redis. invalidate = Image.objects.exclude(pk=img.pk) if invalidate.exists(): Image.objects.invalidate(invalidate[0]) # Rebuild KB schedule_rebuild_kb() return HttpResponseRedirect(img.get_absolute_url()) else: return gallery(request, media_type='image') elif media_type == 'video' and drafts['video']: # We're publishing a video draft! video_form = _init_media_form(VideoForm, request, drafts['video'][0]) if video_form.is_valid(): vid = video_form.save(is_draft=None) if vid.thumbnail: generate_thumbnail.delay(vid, 'poster', 'poster', max_size=settings.WIKI_VIDEO_WIDTH) generate_thumbnail.delay(vid, 'thumbnail', 'thumbnail') # TODO: We can drop this when we start using Redis. invalidate = Video.objects.exclude(pk=vid.pk) if invalidate.exists(): Video.objects.invalidate(invalidate[0]) # Rebuild KB schedule_rebuild_kb() return HttpResponseRedirect(vid.get_absolute_url()) else: return gallery(request, media_type='video') return HttpResponseBadRequest(u'Unrecognized POST request.')
def delete_media(request, media_id, media_type='image'): """Delete media and redirect to gallery view.""" media, media_format = _get_media_info(media_id, media_type) check_media_permissions(media, request.user, 'delete') if request.method == 'GET': # Render the confirmation page return jingo.render(request, 'gallery/confirm_media_delete.html', { 'media': media, 'media_type': media_type, 'media_format': media_format }) # Handle confirm delete form POST log.warning('User %s is deleting %s with id=%s' % (request.user, media_type, media.id)) media.delete() # Rebuild KB schedule_rebuild_kb() return HttpResponseRedirect(reverse('gallery.gallery', args=[media_type]))
def review_revision(request, document_slug, revision_id): """Review a revision of a wiki document.""" rev = get_object_or_404(Revision, pk=revision_id, document__slug=document_slug) doc = rev.document form = ReviewForm() if request.method == 'POST': form = ReviewForm(request.POST) if form.is_valid() and not rev.reviewed: # Don't allow revisions to be reviewed twice rev.is_approved = 'approve' in request.POST rev.reviewer = request.user rev.reviewed = datetime.now() if form.cleaned_data['significance']: rev.significance = form.cleaned_data['significance'] rev.save() # Send notification to revision creator. msg = form.cleaned_data['comment'] send_reviewed_notification.delay(rev, doc, msg) # If approved, send approved notification send_approved_notification.delay(rev, doc) # Schedule KB rebuild? schedule_rebuild_kb() return HttpResponseRedirect(reverse('wiki.document_revisions', args=[document_slug])) if doc.parent: # A translation template = 'wiki/review_translation.html' else: template = 'wiki/review_revision.html' data = {'revision': rev, 'document': doc, 'form': form} data.update(SHOWFOR_DATA) return jingo.render(request, template, data)
def test_dont_queue(self, get, delay): settings.WIKI_REBUILD_ON_DEMAND = False schedule_rebuild_kb() assert not get.called assert not delay.called
def test_task_queue(self, delay): celery.conf.ALWAYS_EAGER = False schedule_rebuild_kb() assert cache.get(settings.WIKI_REBUILD_TOKEN) assert delay.called
def test_already_queued(self, delay): cache.set(settings.WIKI_REBUILD_TOKEN, True) schedule_rebuild_kb() assert cache.get(settings.WIKI_REBUILD_TOKEN) assert not delay.called
def _maybe_schedule_rebuild(form): """Try to schedule a KB rebuild if a title or slug has changed.""" if 'title' in form.changed_data or 'slug' in form.changed_data: schedule_rebuild_kb()
def test_eager_queue(self, delay): schedule_rebuild_kb() assert not cache.get(settings.WIKI_REBUILD_TOKEN) assert not delay.called
def test_eager_queue(self, switch_is_active, delay): switch_is_active.return_value = True schedule_rebuild_kb() assert not cache.get(settings.WIKI_REBUILD_TOKEN) assert not delay.called
def review_revision(request, document_slug, revision_id): """Review a revision of a wiki document.""" rev = get_object_or_404(Revision, pk=revision_id, document__slug=document_slug) doc = rev.document form = ReviewForm() # Don't ask significance if this doc is a translation or if it has no # former approved versions: should_ask_significance = not doc.parent and doc.current_revision if request.method == 'POST': form = ReviewForm(request.POST) if form.is_valid() and not rev.reviewed: # Don't allow revisions to be reviewed twice rev.is_approved = 'approve' in request.POST rev.reviewer = request.user rev.reviewed = datetime.now() if should_ask_significance and form.cleaned_data['significance']: rev.significance = form.cleaned_data['significance'] # If document is localizable and revision was approved and # user has permission, set the is_ready_for_localization value. if (doc.is_localizable and rev.is_approved and request.user.has_perm('wiki.mark_ready_for_l10n')): rev.is_ready_for_localization = form.cleaned_data[ 'is_ready_for_localization'] rev.save() # Send notifications of approvedness and readiness: if rev.is_ready_for_localization or rev.is_approved: events = [ApproveRevisionInLocaleEvent(rev)] if rev.is_ready_for_localization: events.append(ReadyRevisionEvent(rev)) ApprovedOrReadyUnion(*events).fire(exclude=[rev.creator, request.user]) # Send an email (not really a "notification" in the sense that # there's a Watch table entry) to revision creator. msg = form.cleaned_data['comment'] send_reviewed_notification.delay(rev, doc, msg) # Schedule KB rebuild? statsd.incr('wiki.review') schedule_rebuild_kb() return HttpResponseRedirect(reverse('wiki.document_revisions', args=[document_slug])) if doc.parent: # A translation # For diffing the based_on revision against, to help the user see if he # translated all the recent changes: parent_revision = doc.parent.localizable_or_latest_revision() template = 'wiki/review_translation.html' else: parent_revision = None template = 'wiki/review_revision.html' data = {'revision': rev, 'document': doc, 'form': form, 'parent_revision': parent_revision, 'should_ask_significance': should_ask_significance} data.update(SHOWFOR_DATA) return jingo.render(request, template, data)
def review_revision(request, document_slug, revision_id): """Review a revision of a wiki document.""" rev = get_object_or_404(Revision, pk=revision_id, document__slug=document_slug) doc = rev.document form = ReviewForm( initial={'needs_change': doc.needs_change, 'needs_change_comment': doc.needs_change_comment}) # Don't ask significance if this doc is a translation or if it has no # former approved versions: should_ask_significance = not doc.parent and doc.current_revision based_on_revs = doc.revisions.all() last_approved_date = getattr(doc.current_revision, 'created', datetime.fromordinal(1)) based_on_revs = based_on_revs.filter(created__gt=last_approved_date) revision_contributors = list(set( based_on_revs.values_list('creator__username', flat=True))) # Don't include the reviewer in the recent contributors list. if request.user.username in revision_contributors: revision_contributors.remove(request.user.username) if request.method == 'POST': form = ReviewForm(request.POST) if form.is_valid() and not rev.reviewed: # Don't allow revisions to be reviewed twice rev.is_approved = 'approve' in request.POST rev.reviewer = request.user rev.reviewed = datetime.now() if should_ask_significance and form.cleaned_data['significance']: rev.significance = form.cleaned_data['significance'] # If document is localizable and revision was approved and # user has permission, set the is_ready_for_localization value. if (doc.is_localizable and rev.is_approved and request.user.has_perm('wiki.mark_ready_for_l10n')): rev.is_ready_for_localization = form.cleaned_data[ 'is_ready_for_localization'] # If the revision is ready for l10n, store the date # and the user. if rev.is_ready_for_localization: rev.readied_for_localization = rev.reviewed rev.readied_for_localization_by = rev.reviewer rev.save() # Update the needs change bit (if approved, default language and # user has permission). if (doc.locale == settings.WIKI_DEFAULT_LANGUAGE and doc.allows_editing_by(request.user) and rev.is_approved): doc.needs_change = form.cleaned_data['needs_change'] doc.needs_change_comment = \ form.cleaned_data['needs_change_comment'] doc.save() # Send notifications of approvedness and readiness: if rev.is_ready_for_localization or rev.is_approved: events = [ApproveRevisionInLocaleEvent(rev)] if rev.is_ready_for_localization: events.append(ReadyRevisionEvent(rev)) ApprovedOrReadyUnion(*events).fire(exclude=[rev.creator, request.user]) # Send an email (not really a "notification" in the sense that # there's a Watch table entry) to revision creator. msg = form.cleaned_data['comment'] send_reviewed_notification.delay(rev, doc, msg) send_contributor_notification(based_on_revs, rev, doc, msg) # Schedule KB rebuild? statsd.incr('wiki.review') schedule_rebuild_kb() return HttpResponseRedirect(reverse('wiki.document_revisions', args=[document_slug])) if doc.parent: # A translation # For diffing the based_on revision against, to help the user see if he # translated all the recent changes: parent_revision = (rev.based_on or doc.parent.localizable_or_latest_revision()) template = 'wiki/review_translation.html' else: parent_revision = None template = 'wiki/review_revision.html' data = {'revision': rev, 'document': doc, 'form': form, 'parent_revision': parent_revision, 'revision_contributors': list(revision_contributors), 'should_ask_significance': should_ask_significance} data.update(showfor_data()) return render(request, template, data)
def test_dont_queue(self, switch_is_active, get, delay): switch_is_active.return_value = False schedule_rebuild_kb() assert not get.called assert not delay.called
def test_already_queued(self, switch_is_active, delay): switch_is_active.return_value = True cache.set(settings.WIKI_REBUILD_TOKEN, True) schedule_rebuild_kb() assert cache.get(settings.WIKI_REBUILD_TOKEN) assert not delay.called
def test_task_queue(self, switch_is_active, delay): switch_is_active.return_value = True celery.conf.ALWAYS_EAGER = False schedule_rebuild_kb() assert cache.get(settings.WIKI_REBUILD_TOKEN) assert delay.called
def review_revision(request, document_slug, revision_id): """Review a revision of a wiki document.""" rev = get_object_or_404(Revision, pk=revision_id, document__slug=document_slug) doc = rev.document form = ReviewForm(initial={"needs_change": doc.needs_change, "needs_change_comment": doc.needs_change_comment}) # Don't ask significance if this doc is a translation or if it has no # former approved versions: should_ask_significance = not doc.parent and doc.current_revision based_on_revs = doc.revisions.all() last_approved_date = getattr(doc.current_revision, "created", datetime.fromordinal(1)) based_on_revs = based_on_revs.filter(created__gt=last_approved_date) recent_contributors = based_on_revs.values_list("creator__username", flat=True) if request.method == "POST": form = ReviewForm(request.POST) if form.is_valid() and not rev.reviewed: # Don't allow revisions to be reviewed twice rev.is_approved = "approve" in request.POST rev.reviewer = request.user rev.reviewed = datetime.now() if should_ask_significance and form.cleaned_data["significance"]: rev.significance = form.cleaned_data["significance"] # If document is localizable and revision was approved and # user has permission, set the is_ready_for_localization value. if doc.is_localizable and rev.is_approved and request.user.has_perm("wiki.mark_ready_for_l10n"): rev.is_ready_for_localization = form.cleaned_data["is_ready_for_localization"] rev.save() # Update the needs change bit (if approved, default language and # user has permission). if doc.locale == settings.WIKI_DEFAULT_LANGUAGE and doc.allows_editing_by(request.user) and rev.is_approved: doc.needs_change = form.cleaned_data["needs_change"] doc.needs_change_comment = form.cleaned_data["needs_change_comment"] doc.save() # Send notifications of approvedness and readiness: if rev.is_ready_for_localization or rev.is_approved: events = [ApproveRevisionInLocaleEvent(rev)] if rev.is_ready_for_localization: events.append(ReadyRevisionEvent(rev)) ApprovedOrReadyUnion(*events).fire(exclude=[rev.creator, request.user]) # Send an email (not really a "notification" in the sense that # there's a Watch table entry) to revision creator. msg = form.cleaned_data["comment"] send_reviewed_notification.delay(rev, doc, msg) send_contributor_notification(based_on_revs, rev, doc, msg) # Schedule KB rebuild? statsd.incr("wiki.review") schedule_rebuild_kb() return HttpResponseRedirect(reverse("wiki.document_revisions", args=[document_slug])) if doc.parent: # A translation # For diffing the based_on revision against, to help the user see if he # translated all the recent changes: parent_revision = doc.parent.localizable_or_latest_revision() template = "wiki/review_translation.html" else: parent_revision = None template = "wiki/review_revision.html" data = { "revision": rev, "document": doc, "form": form, "parent_revision": parent_revision, "recent_contributors": list(recent_contributors), "should_ask_significance": should_ask_significance, } data.update(SHOWFOR_DATA) return jingo.render(request, template, data)
def review_revision(request, document_slug, revision_id): """Review a revision of a wiki document.""" rev = get_object_or_404(Revision, pk=revision_id, document__slug=document_slug) doc = rev.document form = ReviewForm( initial={ 'needs_change': doc.needs_change, 'needs_change_comment': doc.needs_change_comment }) # Don't ask significance if this doc is a translation or if it has no # former approved versions: should_ask_significance = not doc.parent and doc.current_revision based_on_revs = doc.revisions.all() last_approved_date = getattr(doc.current_revision, 'created', datetime.fromordinal(1)) based_on_revs = based_on_revs.filter(created__gt=last_approved_date) revision_contributors = list( set(based_on_revs.values_list('creator__username', flat=True))) # Don't include the reviewer in the recent contributors list. if request.user.username in revision_contributors: revision_contributors.remove(request.user.username) if request.method == 'POST': form = ReviewForm(request.POST) if form.is_valid() and not rev.reviewed: # Don't allow revisions to be reviewed twice rev.is_approved = 'approve' in request.POST rev.reviewer = request.user rev.reviewed = datetime.now() if should_ask_significance and form.cleaned_data['significance']: rev.significance = form.cleaned_data['significance'] # If document is localizable and revision was approved and # user has permission, set the is_ready_for_localization value. if (doc.is_localizable and rev.is_approved and request.user.has_perm('wiki.mark_ready_for_l10n')): rev.is_ready_for_localization = form.cleaned_data[ 'is_ready_for_localization'] rev.save() # Update the needs change bit (if approved, default language and # user has permission). if (doc.locale == settings.WIKI_DEFAULT_LANGUAGE and doc.allows_editing_by(request.user) and rev.is_approved): doc.needs_change = form.cleaned_data['needs_change'] doc.needs_change_comment = \ form.cleaned_data['needs_change_comment'] doc.save() # Send notifications of approvedness and readiness: if rev.is_ready_for_localization or rev.is_approved: events = [ApproveRevisionInLocaleEvent(rev)] if rev.is_ready_for_localization: events.append(ReadyRevisionEvent(rev)) ApprovedOrReadyUnion(*events).fire( exclude=[rev.creator, request.user]) # Send an email (not really a "notification" in the sense that # there's a Watch table entry) to revision creator. msg = form.cleaned_data['comment'] send_reviewed_notification.delay(rev, doc, msg) send_contributor_notification(based_on_revs, rev, doc, msg) # Schedule KB rebuild? statsd.incr('wiki.review') schedule_rebuild_kb() return HttpResponseRedirect( reverse('wiki.document_revisions', args=[document_slug])) if doc.parent: # A translation # For diffing the based_on revision against, to help the user see if he # translated all the recent changes: parent_revision = doc.parent.localizable_or_latest_revision() template = 'wiki/review_translation.html' else: parent_revision = None template = 'wiki/review_revision.html' data = { 'revision': rev, 'document': doc, 'form': form, 'parent_revision': parent_revision, 'revision_contributors': list(revision_contributors), 'should_ask_significance': should_ask_significance } data.update(SHOWFOR_DATA) return jingo.render(request, template, data)