def test_email_about_approval_requested(self): group = Group.objects.create(name='testapprover') event, = Event.objects.all()[:1] Approval.objects.create(event=event, group=group) request = RequestFactory().get('/') sending.email_about_approval_requested( event, group, request ) ok_(not mail.outbox) # because no users belong to the group bob = User.objects.create(email='*****@*****.**') bob.groups.add(group) sending.email_about_approval_requested( event, group, request ) email_sent = mail.outbox[-1] ok_(email_sent.alternatives) eq_(email_sent.recipients(), [bob.email]) ok_(event.title in email_sent.subject) ok_(event.title in email_sent.body) ok_(group.name in email_sent.body) ok_(event.creator.email in email_sent.body) ok_(reverse('manage:approvals') in email_sent.body)
def _event_process(request, form, event): """Generate and clean associated event data for an event request or event edit: timezone application, approvals update and notifications, creator and modifier.""" if not event.creator: event.creator = request.user event.modified_user = request.user if event.location: tz = pytz.timezone(event.location.timezone) event.start_time = tz_apply(event.start_time, tz) if 'approvals' in form.cleaned_data: event.save() approvals_old = [app.group for app in event.approval_set.all()] approvals_new = form.cleaned_data['approvals'] approvals_add = set(approvals_new).difference(approvals_old) for approval in approvals_add: group = Group.objects.get(name=approval) app = Approval.objects.create(group=group, event=event) sending.email_about_approval_requested( event, group, request ) # Note! we currently do not allow approvals # to be "un-requested". That's because the email has already # gone out and it's too late now. if 'curated_groups' in form.cleaned_data: # because this form field acts like "tags", # we split them by , names = [ x.strip() for x in form.cleaned_data['curated_groups'].split(',') if x.strip() ] if names: all = mozillians.get_all_groups_cached() for name in names: group, __ = CuratedGroup.objects.get_or_create( event=event, name=name ) found = [x for x in all if x['name'] == name] if found and found[0]['url'] != group.url: group.url = found[0]['url'] group.save() # delete any we had before that aren't submitted any more ( CuratedGroup.objects .filter(event=event) .exclude(name__in=names) .delete() )
def event_publish(request, event): if event.status != Event.STATUS_INITIATED: return http.HttpResponseBadRequest("Not in an initiated state") # there has to be a Vid.ly video tag = event.template_environment['tag'] submission = None qs = VidlySubmission.objects.filter(event=event, tag=tag) for each in qs.order_by('-submission_time'): submission = each break assert submission, "Event has no vidly submission" groups = [] with transaction.atomic(): results = vidly.query(tag).get(tag, {}) # Let's check the privacy/tokenization of the video. # What matters (source of truth) is the event's privacy state. if event.privacy != Event.PRIVACY_PUBLIC and results: # make sure the submission the the video IS token protected if not submission.token_protection: submission.token_protection = True submission.save() if results['Private'] == 'false': # We can only do this if the video has been successfully # transcoded. if results['Status'] == 'Finished': vidly.update_media_protection( tag, True ) if results.get('Status') == 'Finished': event.status = Event.STATUS_SCHEDULED # If it's definitely finished, it means we managed to ask # Vid.ly this question before Vid.ly had a chance to ping # us on the webhook. Might as well set it now. if not event.archive_time: event.archive_time = timezone.now() else: # vidly hasn't finished processing it yet event.status = Event.STATUS_PENDING event.save() if not event.picture: # assign the default placeholder picture if there is one try: event.picture = Picture.objects.get(default_placeholder=True) event.save() except Picture.DoesNotExist: # pragma: no cover pass if not event.channels.all(): # forcibly put it in the default channel(s) for channel in Channel.objects.filter(default=True): event.channels.add(channel) if not Discussion.objects.filter(event=event): discussion = Discussion.objects.create( event=event, enabled=True, notify_all=True ) discussion.moderators.add(event.creator) if event.privacy == Event.PRIVACY_PUBLIC: for topic in event.topics.all(): for group in topic.groups.all(): if group not in groups: groups.append(group) for group in groups: Approval.objects.create(event=event, group=group) for group in groups: sending.email_about_approval_requested( event, group, request ) return True
def suggestion_review(request, id): event = get_object_or_404(SuggestedEvent, pk=id) real_event_form = None comment_form = forms.SuggestedEventCommentForm() if request.method == 'POST': if request.POST.get('unbounce'): event.submitted = timezone.now() event.save() return redirect('manage:suggestion_review', event.pk) if not event.submitted: return http.HttpResponseBadRequest('Not submitted') form = forms.AcceptSuggestedEventForm( request.POST, instance=event, ) if request.POST.get('save_comment'): comment_form = forms.SuggestedEventCommentForm(data=request.POST) if comment_form.is_valid(): comment = SuggestedEventComment.objects.create( comment=comment_form.cleaned_data['comment'].strip(), user=request.user, suggested_event=event ) sending.email_about_suggestion_comment( comment, request.user, request ) messages.info( request, 'Comment added and %s notified.' % comment.user.email ) return redirect('manage:suggestion_review', event.pk) reject = request.POST.get('reject') if reject: form.fields['review_comments'].required = True if not request.POST.get('save_comment') and form.is_valid(): form.save() if reject: event.submitted = None event.status = SuggestedEvent.STATUS_REJECTED event.save() sending.email_about_rejected_suggestion( event, request.user, request ) messages.info( request, 'Suggested event bounced back and %s has been emailed' % (event.user.email,) ) url = reverse('manage:suggestions') return redirect(url) else: dict_event = { 'title': event.title, 'description': event.description, 'short_description': event.short_description, 'start_time': event.start_time, 'timezone': event.location.timezone, 'location': event.location.pk, 'channels': [x.pk for x in event.channels.all()], 'call_info': event.call_info, 'privacy': event.privacy, 'estimated_duration': event.estimated_duration, 'topics': [x.pk for x in event.topics.all()], } real_event_form = forms.EventRequestForm( data=dict_event, ) real_event_form.fields['placeholder_img'].required = False if real_event_form.is_valid(): real = real_event_form.save(commit=False) real.placeholder_img = event.placeholder_img real.picture = event.picture real.slug = event.slug real.additional_links = event.additional_links real.remote_presenters = event.remote_presenters real.creator = request.user real.status = Event.STATUS_SUBMITTED # perhaps we have a default location template # environment if real.location: try: default = ( LocationDefaultEnvironment.objects .get( location=real.location, privacy=real.privacy ) ) real.template = default.template real.template_environment = ( default.template_environment ) except LocationDefaultEnvironment.DoesNotExist: pass real.save() [real.tags.add(x) for x in event.tags.all()] [real.channels.add(x) for x in event.channels.all()] [real.topics.add(x) for x in event.topics.all()] event.accepted = real event.save() # create the necessary approval bits if event.privacy == Event.PRIVACY_PUBLIC: groups = [] for topic in real.topics.filter(is_active=True): for group in topic.groups.all(): if group not in groups: groups.append(group) for group in groups: Approval.objects.create( event=real, group=group, ) sending.email_about_approval_requested( real, group, request ) try: discussion = SuggestedDiscussion.objects.get( event=event, enabled=True ) real_discussion = Discussion.objects.create( enabled=True, event=real, notify_all=discussion.notify_all, moderate_all=discussion.moderate_all, ) for moderator in discussion.moderators.all(): real_discussion.moderators.add(moderator) except SuggestedDiscussion.DoesNotExist: pass # if this is a popcorn event, and there is a default # popcorn template, then assign that if real.popcorn_url: real.status = Event.STATUS_SCHEDULED templates = Template.objects.filter( default_popcorn_template=True ) for template in templates[:1]: real.template = template real.save() sending.email_about_accepted_suggestion( event, real, request ) messages.info( request, 'New event created from suggestion.' ) if real.popcorn_url or not event.upcoming: url = reverse('manage:events') else: url = reverse('manage:event_edit', args=(real.pk,)) return redirect(url) else: print real_event_form.errors else: form = forms.AcceptSuggestedEventForm(instance=event) # we don't need the label for this form layout comment_form.fields['comment'].label = '' comments = ( SuggestedEventComment.objects .filter(suggested_event=event) .select_related('User') .order_by('created') ) discussion = None for each in SuggestedDiscussion.objects.filter(event=event): discussion = each context = { 'event': event, 'form': form, 'real_event_form': real_event_form, 'comment_form': comment_form, 'comments': comments, 'discussion': discussion, } return render(request, 'manage/suggestion_review.html', context)
def event_publish(request, event): if event.status != Event.STATUS_INITIATED: return http.HttpResponseBadRequest("Not in an initiated state") groups = [] with transaction.atomic(): # there has to be a Vid.ly video if 'youtube' in event.template.name.lower(): event.status = Event.STATUS_SCHEDULED else: tag = event.template_environment['tag'] submission = None qs = VidlySubmission.objects.filter(event=event, tag=tag) for each in qs.order_by('-submission_time'): submission = each break assert submission, "Event has no vidly submission" results = vidly.query(tag).get(tag, {}) # Let's check the privacy/tokenization of the video. # What matters (source of truth) is the event's privacy state. if event.privacy != Event.PRIVACY_PUBLIC and results: # make sure the submission the the video IS token protected if not submission.token_protection: submission.token_protection = True submission.save() if results['Private'] == 'false': # We can only do this if the video has been successfully # transcoded. if results['Status'] == 'Finished': vidly.update_media_protection(tag, True) if results.get('Status') == 'Finished': event.status = Event.STATUS_SCHEDULED # If it's definitely finished, it means we managed to ask # Vid.ly this question before Vid.ly had a chance to ping # us on the webhook. Might as well set it now. if not event.archive_time: event.archive_time = timezone.now() else: # vidly hasn't finished processing it yet event.status = Event.STATUS_PROCESSING event.save() if not event.picture and not event.placeholder_img: # assign the default placeholder picture if there is one try: event.picture = Picture.objects.get(default_placeholder=True) event.save() except Picture.DoesNotExist: # pragma: no cover pass if not event.channels.all(): # forcibly put it in the default channel(s) for channel in Channel.objects.filter(default=True): event.channels.add(channel) if not Discussion.objects.filter(event=event): discussion = Discussion.objects.create(event=event, enabled=True, notify_all=True) discussion.moderators.add(event.creator) if event.privacy == Event.PRIVACY_PUBLIC: for topic in event.topics.all(): for group in topic.groups.all(): if group not in groups: groups.append(group) for group in groups: Approval.objects.create(event=event, group=group) for group in groups: sending.email_about_approval_requested(event, group, request) return True
def event_publish(request, event): # context = {} if event.status != Event.STATUS_INITIATED: return http.HttpResponseBadRequest("Not in an initiated state") # there has to be a Vid.ly video tag = event.template_environment['tag'] submission = None qs = VidlySubmission.objects.filter(event=event, tag=tag) for each in qs.order_by('-submission_time'): submission = each break assert submission, "Event has no vidly submission" permissions = Permission.objects.filter(codename='change_approval') groups = Group.objects.filter(permissions__in=permissions) with transaction.atomic(): results = vidly.query(tag).get(tag, {}) if results.get('Status') == 'Finished': event.status = Event.STATUS_SCHEDULED # If it's definitely finished, it means we managed to ask # Vid.ly this question before Vid.ly had a chance to ping # us on the webhook. Might as well set it now. if not event.archive_time: event.archive_time = timezone.now() else: # vidly hasn't finished processing it yet event.status = Event.STATUS_PENDING event.save() if not event.picture: # assign the default placeholder picture if there is one try: event.picture = Picture.objects.get(default_placeholder=True) event.save() except Picture.DoesNotExist: # pragma: no cover pass if not event.channels.all(): # forcibly put it in the default channel(s) for channel in Channel.objects.filter(default=True): event.channels.add(channel) if not Discussion.objects.filter(event=event): discussion = Discussion.objects.create( event=event, enabled=True, notify_all=True ) discussion.moderators.add(event.creator) if event.privacy == Event.PRIVACY_PUBLIC: for group in groups: Approval.objects.create(event=event, group=group) for group in groups: sending.email_about_approval_requested( event, group, request ) return True
def suggestion_review(request, id): event = get_object_or_404(SuggestedEvent, pk=id) real_event_form = None comment_form = forms.SuggestedEventCommentForm() if request.method == 'POST': if not event.submitted: return http.HttpResponseBadRequest('Not submitted') form = forms.AcceptSuggestedEventForm( request.POST, instance=event, ) if request.POST.get('save_comment'): comment_form = forms.SuggestedEventCommentForm(data=request.POST) if comment_form.is_valid(): comment = SuggestedEventComment.objects.create( comment=comment_form.cleaned_data['comment'].strip(), user=request.user, suggested_event=event) sending.email_about_suggestion_comment(comment, request.user, request) messages.info( request, 'Comment added and %s notified.' % comment.user.email) return redirect('manage:suggestion_review', event.pk) reject = request.POST.get('reject') if reject: form.fields['review_comments'].required = True if not request.POST.get('save_comment') and form.is_valid(): form.save() if reject: event.submitted = None event.status = SuggestedEvent.STATUS_REJECTED event.save() sending.email_about_rejected_suggestion( event, request.user, request) messages.info( request, 'Suggested event bounced back and %s has been emailed' % (event.user.email, )) url = reverse('manage:suggestions') return redirect(url) else: dict_event = { 'title': event.title, 'description': event.description, 'short_description': event.short_description, 'start_time': event.start_time, 'timezone': event.location.timezone, 'location': event.location.pk, 'channels': [x.pk for x in event.channels.all()], 'call_info': event.call_info, 'privacy': event.privacy, 'popcorn_url': event.popcorn_url, 'estimated_duration': event.estimated_duration, 'topics': [x.pk for x in event.topics.all()], } if dict_event['popcorn_url'] == 'https://': dict_event['popcorn_url'] = '' real_event_form = forms.EventRequestForm(data=dict_event, ) real_event_form.fields['placeholder_img'].required = False if real_event_form.is_valid(): real = real_event_form.save(commit=False) real.placeholder_img = event.placeholder_img real.picture = event.picture real.slug = event.slug real.additional_links = event.additional_links real.remote_presenters = event.remote_presenters real.creator = request.user if real.popcorn_url and not event.upcoming: real.archive_time = real.start_time if event.upcoming: real.status = Event.STATUS_SUBMITTED # perhaps we have a default location template # environment if real.location: try: default = ( LocationDefaultEnvironment.objects.get( location=real.location, privacy=real.privacy)) real.template = default.template real.template_environment = ( default.template_environment) except LocationDefaultEnvironment.DoesNotExist: pass else: real.status = Event.STATUS_PENDING real.save() [real.tags.add(x) for x in event.tags.all()] [real.channels.add(x) for x in event.channels.all()] [real.topics.add(x) for x in event.topics.all()] event.accepted = real event.save() # create the necessary approval bits if event.privacy == Event.PRIVACY_PUBLIC: groups = [] for topic in real.topics.filter(is_active=True): for group in topic.groups.all(): if group not in groups: groups.append(group) for group in groups: Approval.objects.create( event=real, group=group, ) sending.email_about_approval_requested( real, group, request) try: discussion = SuggestedDiscussion.objects.get( event=event, enabled=True) real_discussion = Discussion.objects.create( enabled=True, event=real, notify_all=discussion.notify_all, moderate_all=discussion.moderate_all, ) for moderator in discussion.moderators.all(): real_discussion.moderators.add(moderator) except SuggestedDiscussion.DoesNotExist: pass # if this is a popcorn event, and there is a default # popcorn template, then assign that if real.popcorn_url: real.status = Event.STATUS_SCHEDULED templates = Template.objects.filter( default_popcorn_template=True) for template in templates[:1]: real.template = template real.save() sending.email_about_accepted_suggestion( event, real, request) messages.info(request, 'New event created from suggestion.') if real.popcorn_url or not event.upcoming: url = reverse('manage:events') else: url = reverse('manage:event_edit', args=(real.pk, )) return redirect(url) else: print real_event_form.errors else: form = forms.AcceptSuggestedEventForm(instance=event) # we don't need the label for this form layout comment_form.fields['comment'].label = '' comments = (SuggestedEventComment.objects.filter( suggested_event=event).select_related('User').order_by('created')) discussion = None for each in SuggestedDiscussion.objects.filter(event=event): discussion = each context = { 'event': event, 'form': form, 'real_event_form': real_event_form, 'comment_form': comment_form, 'comments': comments, 'discussion': discussion, } return render(request, 'manage/suggestion_review.html', context)
def suggestion_review(request, id): event = get_object_or_404(SuggestedEvent, pk=id) real_event_form = None comment_form = forms.SuggestedEventCommentForm() if request.method == "POST": if request.POST.get("unbounce"): event.submitted = timezone.now() event.save() return redirect("manage:suggestion_review", event.pk) if not event.submitted: return http.HttpResponseBadRequest("Not submitted") form = forms.AcceptSuggestedEventForm(request.POST, instance=event) if request.POST.get("save_comment"): comment_form = forms.SuggestedEventCommentForm(data=request.POST) if comment_form.is_valid(): comment = SuggestedEventComment.objects.create( comment=comment_form.cleaned_data["comment"].strip(), user=request.user, suggested_event=event ) sending.email_about_suggestion_comment(comment, request.user, request) messages.info(request, "Comment added and %s notified." % comment.user.email) return redirect("manage:suggestion_review", event.pk) reject = request.POST.get("reject") if reject: form.fields["review_comments"].required = True if not request.POST.get("save_comment") and form.is_valid(): form.save() if reject: event.submitted = None event.status = SuggestedEvent.STATUS_REJECTED event.save() sending.email_about_rejected_suggestion(event, request.user, request) messages.info(request, "Suggested event bounced back and %s has been emailed" % (event.user.email,)) url = reverse("manage:suggestions") return redirect(url) else: dict_event = { "title": event.title, "description": event.description, "short_description": event.short_description, "start_time": event.start_time, "timezone": event.location.timezone, "location": event.location.pk, "channels": [x.pk for x in event.channels.all()], "call_info": event.call_info, "privacy": event.privacy, "popcorn_url": event.popcorn_url, "estimated_duration": event.estimated_duration, "topics": [x.pk for x in event.topics.all()], } if dict_event["popcorn_url"] == "https://": dict_event["popcorn_url"] = "" real_event_form = forms.EventRequestForm(data=dict_event) real_event_form.fields["placeholder_img"].required = False if real_event_form.is_valid(): real = real_event_form.save(commit=False) real.placeholder_img = event.placeholder_img real.picture = event.picture real.slug = event.slug real.additional_links = event.additional_links real.remote_presenters = event.remote_presenters real.creator = request.user if real.popcorn_url and not event.upcoming: real.archive_time = real.start_time if event.upcoming: real.status = Event.STATUS_SUBMITTED # perhaps we have a default location template # environment if real.location: try: default = LocationDefaultEnvironment.objects.get( location=real.location, privacy=real.privacy ) real.template = default.template real.template_environment = default.template_environment except LocationDefaultEnvironment.DoesNotExist: pass else: real.status = Event.STATUS_PENDING real.save() [real.tags.add(x) for x in event.tags.all()] [real.channels.add(x) for x in event.channels.all()] [real.topics.add(x) for x in event.topics.all()] event.accepted = real event.save() # create the necessary approval bits if event.privacy == Event.PRIVACY_PUBLIC: groups = [] for topic in real.topics.filter(is_active=True): for group in topic.groups.all(): if group not in groups: groups.append(group) for group in groups: Approval.objects.create(event=real, group=group) sending.email_about_approval_requested(real, group, request) try: discussion = SuggestedDiscussion.objects.get(event=event, enabled=True) real_discussion = Discussion.objects.create( enabled=True, event=real, notify_all=discussion.notify_all, moderate_all=discussion.moderate_all, ) for moderator in discussion.moderators.all(): real_discussion.moderators.add(moderator) except SuggestedDiscussion.DoesNotExist: pass # if this is a popcorn event, and there is a default # popcorn template, then assign that if real.popcorn_url: real.status = Event.STATUS_SCHEDULED templates = Template.objects.filter(default_popcorn_template=True) for template in templates[:1]: real.template = template real.save() sending.email_about_accepted_suggestion(event, real, request) messages.info(request, "New event created from suggestion.") if real.popcorn_url or not event.upcoming: url = reverse("manage:events") else: url = reverse("manage:event_edit", args=(real.pk,)) return redirect(url) else: print real_event_form.errors else: form = forms.AcceptSuggestedEventForm(instance=event) # we don't need the label for this form layout comment_form.fields["comment"].label = "" comments = SuggestedEventComment.objects.filter(suggested_event=event).select_related("User").order_by("created") discussion = None for each in SuggestedDiscussion.objects.filter(event=event): discussion = each context = { "event": event, "form": form, "real_event_form": real_event_form, "comment_form": comment_form, "comments": comments, "discussion": discussion, } return render(request, "manage/suggestion_review.html", context)