Пример #1
0
def send_template_mail(sender,
                       receiver,
                       subject,
                       templatename,
                       templateattr={},
                       usergenerated=False,
                       cc=None,
                       replyto=None,
                       receivername=None,
                       sendername=None,
                       messageid=None):
    d = {
        'link_root': settings.SITE_ROOT,
    }
    d.update(templateattr)
    send_simple_mail(sender,
                     receiver,
                     subject,
                     template_to_string(templatename, d),
                     usergenerated=usergenerated,
                     cc=cc,
                     replyto=replyto,
                     receivername=receivername,
                     sendername=sendername,
                     messageid=messageid)
Пример #2
0
def _submitted_item_withdraw(request, objtype, model, obj):
    if obj.modstate != ModerationState.PENDING:
        # Can only withdraw if it's in pending state
        return HttpResponseRedirect("/account/edit/{}/".format(objtype))

    obj.modstate = ModerationState.CREATED
    obj.send_notification = False
    if obj.twomoderators:
        obj.firstmoderator = None
        obj.save(update_fields=['modstate', 'firstmoderator'])
    else:
        obj.save(update_fields=[
            'modstate',
        ])

    send_simple_mail(
        settings.NOTIFICATION_FROM,
        settings.NOTIFICATION_EMAIL,
        "{} '{}' withdrawn from moderation".format(
            model._meta.verbose_name.capitalize(), obj.title),
        "{} {} with title {} withdrawn from moderation by {}".format(
            model._meta.verbose_name.capitalize(), obj.id, obj.title,
            request.user.username),
    )
    return HttpResponseRedirect("/account/edit/{}/".format(objtype))
Пример #3
0
    def handle(self, *args, **options):
        with transaction.atomic():
            newly_visible = []
            for s in SecurityPatch.objects.filter(cve_visible=False):
                r = requests.get(s.cvelink, timeout=10)
                if r.status_code == 200:
                    # RedHat have started requiring both a HTML page and a JSON api call to view
                    # CVEs. Dumb dumb dumb, but what can we do...
                    r = requests.get(
                        'https://access.redhat.com/api/redhat_node/CVE-{}.json'
                        .format(s.cve))
                    if r.status_code == 200:
                        newly_visible.append(s.cve)
                        s.cve_visible = True
                        s.save()
            if newly_visible:
                send_simple_mail(
                    settings.NOTIFICATION_FROM, settings.NOTIFICATION_EMAIL,
                    "CVE entries made public",
                    """The following CVE entries are now public upstream,
and have been made visible on the website.

{0}
""".format("\n".join(newly_visible)))
                list(map(varnish_purge, SecurityPatch.purge_urls))
Пример #4
0
def _submitted_item_submit(request, objtype, model, obj):
    if obj.modstate != ModerationState.CREATED:
        # Can only submit if state is created
        return HttpResponseRedirect("/account/edit/{}/".format(objtype))

    if request.method == 'POST':
        form = ConfirmSubmitForm(obj._meta.verbose_name, data=request.POST)
        if form.is_valid():
            with transaction.atomic():
                obj.modstate = ModerationState.PENDING
                obj.send_notification = False
                obj.save()

                send_simple_mail(settings.NOTIFICATION_FROM,
                                 settings.NOTIFICATION_EMAIL,
                                 "{} '{}' submitted for moderation".format(obj._meta.verbose_name.capitalize(), obj.title),
                                 "{} {} with title '{}' submitted for moderation by {}\n\nModerate at: {}\n".format(
                                     obj._meta.verbose_name.capitalize(),
                                     obj.id,
                                     obj.title,
                                     request.user.username,
                                     '{}/admin/_moderate/{}/{}/'.format(settings.SITE_ROOT, obj._meta.model_name, obj.pk),
                                 ),
                                 )
                return HttpResponseRedirect("/account/edit/{}/".format(objtype))
    else:
        form = ConfirmSubmitForm(obj._meta.verbose_name)

    return render_pgweb(request, 'account', 'account/submit_preview.html', {
        'obj': obj,
        'form': form,
        'objtype': obj._meta.verbose_name,
        'preview': obj.get_preview_fields(),
    })
Пример #5
0
def my_m2m_changed_handler(sender, **kwargs):
    instance = kwargs['instance']
    if getattr(instance, 'send_m2m_notification',
               False) and get_current_user():
        (cl, f) = sender.__name__.split('_')
        if not hasattr(instance, '_stored_m2m'):
            instance._stored_m2m = {}
        if kwargs['action'] == 'pre_clear':
            instance._stored_m2m[f] = set(
                [unicode(t) for t in getattr(instance, f).all()])
        elif kwargs['action'] == 'post_add':
            newset = set([unicode(t) for t in getattr(instance, f).all()])
            added = newset.difference(instance._stored_m2m.get(f, set()))
            removed = instance._stored_m2m.get(f, set()).difference(newset)
            subj = '{0} id {1} has been modified'.format(
                instance._meta.verbose_name, instance.id)
            if added or removed:
                send_simple_mail(
                    settings.NOTIFICATION_FROM, settings.NOTIFICATION_EMAIL,
                    "%s by %s" % (subj, get_current_user()),
                    "The following values for {0} were changed:\n\n{1}\n{2}\n\n"
                    .format(
                        instance._meta.get_field(f).verbose_name,
                        "\n".join([u"Added: %s" % a for a in added]),
                        "\n".join([u"Removed: %s" % r for r in removed]),
                    ))
Пример #6
0
def send_news_email(news):
    html, attachments = render_news_template(news)

    messageid = make_msgid()

    # If configured to, add the tags and sign them so that a pglister delivery system can filter
    # recipients based on it.
    if settings.NEWS_MAIL_TAGKEY:
        date = formatdate(localtime=True)
        tagstr = ",".join([t.urlname for t in news.tags.all()])
        h = hmac.new(
            settings.NEWS_MAIL_TAGKEY.encode('ascii'),
            tagstr.encode('ascii') + messageid.encode('ascii') +
            date.encode('ascii'), hashlib.sha256)
        headers = {
            'X-pglister-tags': tagstr,
            'X-pglister-tagsig': h.hexdigest(),
            'Date': date,
        }
    else:
        headers = {}

    send_simple_mail(
        settings.NEWS_MAIL_SENDER,
        settings.NEWS_MAIL_RECEIVER,
        news.title,
        news.content,
        replyto=news.email.address,
        sendername=news.sentfrom,
        receivername=settings.NEWS_MAIL_RECEIVER_NAME,
        messageid=messageid,
        htmlbody=html,
        attachments=attachments,
        headers=headers,
    )
Пример #7
0
def my_pre_delete_handler(sender, **kwargs):
    instance = kwargs['instance']
    if getattr(instance, 'send_notification', False) and get_current_user():
        send_simple_mail(
            settings.NOTIFICATION_FROM, settings.NOTIFICATION_EMAIL,
            "%s id %s has been deleted by %s" %
            (instance._meta.verbose_name, instance.id, get_current_user()),
            _get_full_text_representation(instance))
Пример #8
0
def my_pre_save_handler(sender, **kwargs):
    instance = kwargs['instance']
    if getattr(instance, 'send_notification', False) and get_current_user():
        (subj, cont) = _get_notification_text(instance)
        if cont:
            cont = _build_url(instance) + "\n\n" + cont
            send_simple_mail(settings.NOTIFICATION_FROM,
                             settings.NOTIFICATION_EMAIL,
                             "%s by %s" % (subj, get_current_user()), cont)
Пример #9
0
def my_pre_save_handler(sender, **kwargs):
	instance = kwargs['instance']
	if getattr(instance, 'send_notification', False):
		(subj, cont) = _get_notification_text(instance)
		if cont:
			cont = _build_url(instance) + "\n\n" + cont
			send_simple_mail(settings.NOTIFICATION_FROM,
							 settings.NOTIFICATION_EMAIL,
							 "%s by %s" % (subj, get_current_user()),
							 cont)
Пример #10
0
def my_pre_delete_handler(sender, **kwargs):
	instance = kwargs['instance']
	if getattr(instance, 'send_notification', False):
		send_simple_mail(settings.NOTIFICATION_FROM,
						 settings.NOTIFICATION_EMAIL,
						 "%s id %s has been deleted by %s" % (
							 instance._meta.verbose_name,
							 instance.id,
							 get_current_user()),
						_get_full_text_representation(instance))
Пример #11
0
def send_template_mail(sender,
                       receiver,
                       subject,
                       templatename,
                       templateattr={},
                       usergenerated=False):
    send_simple_mail(sender,
                     receiver,
                     subject,
                     template_to_string(templatename, templateattr),
                     usergenerated=usergenerated)
Пример #12
0
    def save(self, commit=True):
        model = super(OrganisationForm, self).save(commit=False)

        ops = []
        if self.cleaned_data.get('add_email', None):
            # Create the email record
            e = OrganisationEmail(
                org=model,
                address=self.cleaned_data['add_email'].lower(),
                token=generate_random_token())
            e.save()

            # Send email for confirmation
            send_template_mail(
                settings.NOTIFICATION_FROM,
                e.address,
                "Email address added to postgresql.org organisation",
                'core/org_add_email.txt',
                {
                    'org': model,
                    'email': e,
                },
            )
            ops.append('Added email {}, confirmation request sent'.format(
                e.address))
        if self.cleaned_data.get('remove_email', None):
            for e in self.cleaned_data['remove_email']:
                ops.append('Removed email {}'.format(e.address))
                e.delete()

        if 'add_manager' in self.cleaned_data and self.cleaned_data[
                'add_manager']:
            u = User.objects.get(
                email=self.cleaned_data['add_manager'].lower())
            model.managers.add(u)
            ops.append('Added manager {}'.format(u.username))
        if 'remove_manager' in self.cleaned_data and self.cleaned_data[
                'remove_manager']:
            for toremove in self.cleaned_data['remove_manager']:
                model.managers.remove(toremove)
                ops.append('Removed manager {}'.format(toremove.username))

        if ops:
            send_simple_mail(
                settings.NOTIFICATION_FROM, settings.NOTIFICATION_EMAIL,
                "{0} modified {1}".format(get_current_user().username, model),
                "The following changes were made to {}:\n\n{}".format(
                    model, "\n".join(ops)))
        return model
Пример #13
0
def subscribe(request):
	if request.POST:
		form = SubscribeForm(request.POST)
		if form.is_valid():
			if form.cleaned_data['action'] == 'subscribe':
				mailsubject = "subscribe"
				# Default is get mail and not digest, in which case we send a regular
				# subscribe request. In other cases, we send subscribe-set which also
				# sets those flags.
				if form.cleaned_data['receive'] and not form.cleaned_data['digest']:
					mailtxt = "subscribe %s\n" % form.cleaned_data['lists']
				else:
					tags = []
					if not form.cleaned_data['receive']:
						tags.append('nomail')
					if form.cleaned_data['digest']:
						tags.append('digest')

					mailtxt = "subscribe-set %s %s\n" % (form.cleaned_data['lists'],
														",".join(tags))
			else:
				mailtxt = "unsubscribe %s\n" % form.cleaned_data['lists']
				mailsubject = "unsubscribe"

			send_simple_mail(form.cleaned_data['email'],
							 settings.LISTSERVER_EMAIL,
							 mailsubject,
							 mailtxt)

			return render_to_response('lists/subscribed.html', {
			}, NavContext(request, "community"))
	else:
		# GET, so render up the form
		form = SubscribeForm()

	return render_to_response('lists/subscribe_form.html', {
		'form': form,
		'operation': 'Subscribe',
		'jquery': True,
		'form_intro': """
<b>Note 1:</b> Please ensure you read the <a 
href="https://wiki.postgresql.org/wiki/Archives_Policy">Archive Policy</a>
before posting to the lists.</p>

<p><b>Note 2:</b> Please do not subscribe to mailing lists using e-mail 
accounts protected by mail-back anti-spam systems. These are extremely annoying 
to the list maintainers and other members, and you may be automatically unsubscribed."""
	}, NavContext(request, "community"))
Пример #14
0
def subscribe(request):
	if request.POST:
		form = SubscribeForm(request.POST)
		if form.is_valid():
			if form.cleaned_data['action'] == 'subscribe':
				mailsubject = "subscribe"
				# Default is get mail and not digest, in which case we send a regular
				# subscribe request. In other cases, we send subscribe-set which also
				# sets those flags.
				if form.cleaned_data['receive'] and not form.cleaned_data['digest']:
					mailtxt = "subscribe %s\n" % form.cleaned_data['lists']
				else:
					tags = []
					if not form.cleaned_data['receive']:
						tags.append('nomail')
					if form.cleaned_data['digest']:
						tags.append('digest')

					mailtxt = "subscribe-set %s %s\n" % (form.cleaned_data['lists'],
														",".join(tags))
			else:
				mailtxt = "unsubscribe %s\n" % form.cleaned_data['lists']
				mailsubject = "unsubscribe"

			send_simple_mail(form.cleaned_data['email'],
							 settings.LISTSERVER_EMAIL,
							 mailsubject,
							 mailtxt)

			return render_to_response('lists/subscribed.html', {
			}, NavContext(request, "community"))
	else:
		# GET, so render up the form
		form = SubscribeForm()

	return render_to_response('lists/subscribe_form.html', {
		'form': form,
		'operation': 'Subscribe',
		'jquery': True,
		'form_intro': """
<b>Note 1:</b> Please ensure you read the <a 
href="https://wiki.postgresql.org/wiki/Archives_Policy">Archive Policy</a>
before posting to the lists.</p>

<p><b>Note 2:</b> Please do not subscribe to mailing lists using e-mail 
accounts protected by mail-back anti-spam systems. These are extremely annoying 
to the list maintainers and other members, and you may be automatically unsubscribed."""
	}, NavContext(request, "community"))
Пример #15
0
    def save_model(self, request, obj, form, change):
        if change and self.model.send_notification:
            # We only do processing if something changed, not when adding
            # a new object.
            if request.POST.has_key(
                    'new_notification') and request.POST['new_notification']:
                # Need to send off a new notification. We'll also store
                # it in the database for future reference, of course.
                if not obj.org.email:
                    # Should not happen because we remove the form field. Thus
                    # a hard exception is ok.
                    raise Exception(
                        "Organization does not have an email, canot send notification!"
                    )
                n = ModerationNotification()
                n.objecttype = obj.__class__.__name__
                n.objectid = obj.id
                n.text = request.POST['new_notification']
                n.author = request.user.username
                n.save()

                # Now send an email too
                msgstr = _get_notification_text(
                    request.POST.has_key('remove_after_notify'), obj,
                    request.POST['new_notification'])

                send_simple_mail(settings.NOTIFICATION_FROM, obj.org.email,
                                 "postgresql.org moderation notification",
                                 msgstr)

                # Also generate a mail to the moderators
                send_simple_mail(
                    settings.NOTIFICATION_FROM, settings.NOTIFICATION_EMAIL,
                    "Moderation comment on %s %s" %
                    (obj.__class__._meta.verbose_name, obj.id),
                    _get_moderator_notification_text(
                        request.POST.has_key('remove_after_notify'), obj,
                        request.POST['new_notification'],
                        request.user.username))

                if request.POST.has_key('remove_after_notify'):
                    # Object should not be saved, it should be deleted
                    obj.delete()
                    return

        # Either no notifications, or done with notifications
        super(PgwebAdmin, self).save_model(request, obj, form, change)
Пример #16
0
    def handle(self, *args, **options):
        with transaction.atomic():
            newly_visible = []
            for s in SecurityPatch.objects.filter(cve_visible=False):
                r = requests.get(s.cvelink, timeout=10)
                if r.status_code == 200:
                    newly_visible.append(s.cve)
                    s.cve_visible = True
                    s.save()
            if newly_visible:
                send_simple_mail(settings.NOTIFICATION_FROM,
                                 settings.NOTIFICATION_EMAIL,
                                 "CVE entries made public",
                                 """The following CVE entries are now public upstream,
and have been made visible on the website.

{0}
""".format("\n".join(newly_visible)))
                list(map(varnish_purge, SecurityPatch.purge_urls))
Пример #17
0
    def handle(self, *args, **options):
        with transaction.atomic():
            newly_visible = []
            for s in SecurityPatch.objects.filter(cve_visible=False):
                r = requests.get(s.cvelink, timeout=10)
                if r.status_code == 200:
                    newly_visible.append(s.cve)
                    s.cve_visible = True
                    s.save()
            if newly_visible:
                send_simple_mail(
                    settings.NOTIFICATION_FROM, settings.NOTIFICATION_EMAIL,
                    "CVE entries made public",
                    """The following CVE entries are now public upstream,
and have been made visible on the website.

{0}
""".format("\n".join(newly_visible)))
                map(varnish_purge, SecurityPatch.purge_urls)
Пример #18
0
    def save(self, commit=True):
        model = super(OrganisationForm, self).save(commit=False)
        ops = []
        if 'add_manager' in self.cleaned_data and self.cleaned_data['add_manager']:
            u = User.objects.get(email=self.cleaned_data['add_manager'].lower())
            model.managers.add(u)
            ops.append('Added manager {}'.format(u.username))
        if 'remove_manager' in self.cleaned_data and self.cleaned_data['remove_manager']:
            for toremove in self.cleaned_data['remove_manager']:
                model.managers.remove(toremove)
                ops.append('Removed manager {}'.format(toremove.username))

        if ops:
            send_simple_mail(
                settings.NOTIFICATION_FROM,
                settings.NOTIFICATION_EMAIL,
                "{0} modified managers of {1}".format(get_current_user().username, model),
                "The following changes were made to managers:\n\n{0}".format("\n".join(ops))
            )
        return model
Пример #19
0
    def save_model(self, request, obj, form, change):
        if change and hasattr(self.model, 'send_notification') and self.model.send_notification:
            # We only do processing if something changed, not when adding
            # a new object.
            if 'new_notification' in request.POST and request.POST['new_notification']:
                # Need to send off a new notification. We'll also store
                # it in the database for future reference, of course.
                if not obj.org.email:
                    # Should not happen because we remove the form field. Thus
                    # a hard exception is ok.
                    raise Exception("Organisation does not have an email, canot send notification!")
                n = ModerationNotification()
                n.objecttype = obj.__class__.__name__
                n.objectid = obj.id
                n.text = request.POST['new_notification']
                n.author = request.user.username
                n.save()

                # Now send an email too
                msgstr = _get_notification_text(obj,
                                                request.POST['new_notification'])

                send_simple_mail(settings.NOTIFICATION_FROM,
                                 obj.org.email,
                                 "postgresql.org moderation notification",
                                 msgstr)

                # Also generate a mail to the moderators
                send_simple_mail(
                    settings.NOTIFICATION_FROM,
                    settings.NOTIFICATION_EMAIL,
                    "Moderation comment on %s %s" % (obj.__class__._meta.verbose_name, obj.id),
                    _get_moderator_notification_text(
                        obj,
                        request.POST['new_notification'],
                        request.user.username
                    )
                )

        # Either no notifications, or done with notifications
        super(PgwebAdmin, self).save_model(request, obj, form, change)
Пример #20
0
def simple_form(instancetype,
                itemid,
                request,
                formclass,
                formtemplate='base/form.html',
                redirect='/account/',
                navsection='account',
                fixedfields=None,
                createifempty=False):
    if itemid == 'new':
        instance = instancetype()
        is_new = True
    else:
        is_new = False
        # Regular form item, attempt to edit it
        try:
            int(itemid)
        except ValueError:
            raise Http404("Invalid URL")
        if createifempty:
            (instance,
             wascreated) = instancetype.objects.get_or_create(pk=itemid)
        else:
            instance = get_object_or_404(instancetype, pk=itemid)
        if hasattr(instance, 'submitter'):
            if not instance.submitter == request.user:
                raise PermissionDenied("You are not the owner of this item!")
        elif hasattr(instance, 'verify_submitter'):
            if not instance.verify_submitter(request.user):
                raise PermissionDenied("You are not the owner of this item!")

    if request.method == 'POST':
        # Process this form
        form = formclass(data=request.POST, instance=instance)

        # Save away the old value from the instance before it's saved
        if not is_new:
            old_values = {
                fn: str(getattr(instance, fn))
                for fn in form.changed_data if hasattr(instance, fn)
            }

        if form.is_valid():
            # We are handling notifications, so disable the ones we'd otherwise send
            do_notify = getattr(instance, 'send_notification', False)
            instance.send_notification = False

            if not getattr(instance, 'approved', True) and not is_new:
                # If the object has an "approved" field and it's set to false, we don't
                # bother notifying about the changes. But if it lacks this field, we notify
                # about everything, as well as if the field exists and the item has already
                # been approved.
                # Newly added objects are always notified.
                do_notify = False

            notify = io.StringIO()

            r = form.save(commit=False)
            r.submitter = request.user
            # Set fixed fields. Note that this will not work if the fixed fields are ManyToMany,
            # but we'll fix that sometime in the future
            if fixedfields:
                for k, v in list(fixedfields.items()):
                    setattr(r, k, v)
            r.save()

            # If we have a callback with the current user
            if hasattr(form, 'apply_submitter'):
                form.apply_submitter(r, request.user)
                r.save()

            if is_new:
                subj = 'A new {0} has been added'.format(
                    instance._meta.verbose_name)
                for f in form.fields:
                    notify.write("{}:\n".format(f))
                    if instance._meta.get_field(
                            f) in instance._meta.many_to_many:
                        notify.write("{}\n".format("\n".join(
                            [str(x) for x in form.cleaned_data[f]])))
                    else:
                        notify.write("{}\n".format(str(form.cleaned_data[f])))
                    notify.write("\n")
            else:
                subj = '{0} id {1} has been modified'.format(
                    instance._meta.verbose_name, instance.id)

                for fn in form.changed_data:
                    if not hasattr(instance, fn):
                        continue
                    f = instance._meta.get_field(fn)
                    if f in instance._meta.many_to_many:
                        # m2m field have separate config of notificatgions
                        if getattr(instance, 'send_m2m_notification', False):
                            for f in instance._meta.many_to_many:
                                if f.name in form.cleaned_data:
                                    old = set([
                                        str(x) for x in getattr(
                                            instance, f.name).all()
                                    ])
                                    new = set([
                                        str(x)
                                        for x in form.cleaned_data[f.name]
                                    ])
                                    added = new.difference(old)
                                    removed = old.difference(new)
                                    if added or removed:
                                        notify.write(
                                            "--- {}\n+++ {}\n{}\n{}\n".format(
                                                f.verbose_name,
                                                f.verbose_name,
                                                "\n".join([
                                                    "+ %s" % a for a in added
                                                ]),
                                                "\n".join([
                                                    "- %s" % r for r in removed
                                                ]),
                                            ))
                    else:
                        # Regular field!
                        # Sometimes it shows up as changed even if it hasn't changed, so do
                        # a second check on if the diff is non-empty.
                        diffrows = [
                            x for x in difflib.unified_diff(
                                old_values[f.name].splitlines(),
                                str(form.cleaned_data[f.name]).splitlines(),
                                n=1,
                                lineterm='',
                                fromfile=f.verbose_name,
                                tofile=f.verbose_name,
                            ) if not x.startswith("@@")
                        ]
                        if diffrows:
                            notify.write("\n".join(diffrows))
                            notify.write("\n\n")

            if do_notify and notify.tell():
                send_simple_mail(
                    settings.NOTIFICATION_FROM,
                    settings.NOTIFICATION_EMAIL,
                    "%s by %s" % (subj, request.user.username),
                    "Title: {0}\n\n{1}".format(
                        str(instance),
                        notify.getvalue(),
                    ),
                )
            form.save_m2m()

            return HttpResponseRedirect(redirect)
    else:
        # Generate form
        form = formclass(instance=instance)

    if hasattr(form, 'filter_by_user'):
        form.filter_by_user(request.user)

    for fn in form.fields:
        if fn in getattr(instancetype, 'markdown_fields', []):
            form.fields[fn].widget.attrs.update({'class': 'markdown-content'})

    for togg in getattr(form, 'toggle_fields', []):
        form.fields[togg['name']].widget.attrs.update({
            'data-toggles':
            ','.join(togg['fields']),
            'data-toggle-invert':
            togg['invert'] and 'true' or 'false',
            'class':
            'toggle-checkbox',
        })

    return render_pgweb(
        request, navsection, formtemplate, {
            'form': form,
            'formitemtype': instance._meta.verbose_name,
            'form_intro': hasattr(form, 'form_intro') and form.form_intro
            or None,
            'described_checkboxes': getattr(form, 'described_checkboxes', {}),
            'savebutton': (itemid == "new") and "Submit New" or "Save",
            'operation': (itemid == "new") and "New" or "Edit",
        })
Пример #21
0
def send_template_mail(sender, receiver, subject, templatename, templateattr={}, usergenerated=False):
	send_simple_mail(sender, receiver, subject,
					 template_to_string(templatename, templateattr),
					 usergenerated=usergenerated)
Пример #22
0
def _send_moderation_message(request, obj, message, notice, what):
    if message and notice:
        msg = "{}\n\nThe following further information was provided:\n{}".format(
            message, notice)
    elif notice:
        msg = notice
    else:
        msg = message

    n = ModerationNotification(
        objectid=obj.id,
        objecttype=type(obj).__name__,
        text=msg,
        author=request.user,
    )
    n.save()

    # In the email, add a link back to the item in the bottom
    msg += "\n\nYou can view your {} by going to\n{}/account/edit/{}/".format(
        obj._meta.verbose_name,
        settings.SITE_ROOT,
        obj.account_edit_suburl,
    )

    # Send message to org admins
    if isinstance(obj, Organisation):
        org = obj
    else:
        org = obj.org

    for m in org.managers.all():
        send_simple_mail(
            settings.NOTIFICATION_FROM,
            m.email,
            "Your submitted {} with title {}".format(obj._meta.verbose_name,
                                                     obj.title),
            msg,
            suppress_auto_replies=False,
            receivername='{} {}'.format(m.first_name, m.last_name),
        )

    # Send notification to admins
    if obj.twomoderators and obj.firstmoderator:
        # For two-moderator objects, only one is required to reject or send back for editing. In that case,
        # just log the current user who is the one that did that.
        modname = "{} and {}".format(obj.firstmoderator, request.user)
    else:
        modname = request.user

    if what:
        # If an actual change happened, notify of that
        admmsg = message
        if obj.is_approved:
            admmsg += "\n\nNOTE! This {} was previously approved!!".format(
                obj._meta.verbose_name)

        if notice:
            admmsg += "\n\nModeration notice:\n{}".format(notice)

        if what != "rejected":
            # No point in sending an edit link to a page that doesn't exist anymore
            admmsg += "\n\nEdit at: {}/admin/_moderate/{}/{}/\n".format(
                settings.SITE_ROOT, obj._meta.model_name, obj.id)

        send_simple_mail(
            settings.NOTIFICATION_FROM, settings.NOTIFICATION_EMAIL,
            "{} '{}' {} by {}".format(obj._meta.verbose_name.capitalize(),
                                      obj.title, what, modname), admmsg)
    elif notice:
        # There was no change, but there was a moderation notice. We still want to inform the moderators that this happened
        admmsg = "No changes were made, but the following notice was sent:\n{}\n\nEdit at: {}/admin/_moderate/{}/{}/\n".format(
            notice,
            settings.SITE_ROOT,
            obj._meta.model_name,
            obj.id,
        )
        send_simple_mail(
            settings.NOTIFICATION_FROM, settings.NOTIFICATION_EMAIL,
            "Moderation notice on '{}' {} by {}".format(
                obj._meta.verbose_name.capitalize(), obj.title,
                modname), admmsg)
Пример #23
0
def simple_form(instancetype, itemid, request, formclass, formtemplate='base/form.html', redirect='/account/', navsection='account', fixedfields=None, createifempty=False):
    if itemid == 'new':
        instance = instancetype()
        is_new = True
    else:
        is_new = False
        # Regular form item, attempt to edit it
        try:
            int(itemid)
        except ValueError:
            raise Http404("Invalid URL")
        if createifempty:
            (instance, wascreated) = instancetype.objects.get_or_create(pk=itemid)
        else:
            instance = get_object_or_404(instancetype, pk=itemid)
        if hasattr(instance, 'submitter'):
            if not instance.submitter == request.user:
                raise Exception("You are not the owner of this item!")
        elif hasattr(instance, 'verify_submitter'):
            if not instance.verify_submitter(request.user):
                raise Exception("You are not the owner of this item!")

    if request.method == 'POST':
        # Process this form
        form = formclass(data=request.POST, instance=instance)

        # Save away the old value from the instance before it's saved
        if not is_new:
            old_values = {fn: str(getattr(instance, fn)) for fn in form.changed_data if hasattr(instance, fn)}

        if form.is_valid():
            # We are handling notifications, so disable the ones we'd otherwise send
            do_notify = getattr(instance, 'send_notification', False)
            instance.send_notification = False

            if not getattr(instance, 'approved', True) and not is_new:
                # If the object has an "approved" field and it's set to false, we don't
                # bother notifying about the changes. But if it lacks this field, we notify
                # about everything, as well as if the field exists and the item has already
                # been approved.
                # Newly added objects are always notified.
                do_notify = False

            notify = io.StringIO()

            r = form.save(commit=False)
            r.submitter = request.user
            # Set fixed fields. Note that this will not work if the fixed fields are ManyToMany,
            # but we'll fix that sometime in the future
            if fixedfields:
                for k, v in list(fixedfields.items()):
                    setattr(r, k, v)
            r.save()

            # If we have a callback with the current user
            if hasattr(form, 'apply_submitter'):
                form.apply_submitter(r, request.user)
                r.save()

            if is_new:
                subj = 'A new {0} has been added'.format(instance._meta.verbose_name)
                for f in form.fields:
                    notify.write("{}:\n".format(f))
                    if instance._meta.get_field(f) in instance._meta.many_to_many:
                        notify.write("{}\n".format("\n".join([str(x) for x in form.cleaned_data[f]])))
                    else:
                        notify.write("{}\n".format(str(form.cleaned_data[f])))
                    notify.write("\n")
            else:
                subj = '{0} id {1} has been modified'.format(instance._meta.verbose_name, instance.id)

                for fn in form.changed_data:
                    if not hasattr(instance, fn):
                        continue
                    f = instance._meta.get_field(fn)
                    if f in instance._meta.many_to_many:
                        # m2m field have separate config of notificatgions
                        if getattr(instance, 'send_m2m_notification', False):
                            for f in instance._meta.many_to_many:
                                if f.name in form.cleaned_data:
                                    old = set([str(x) for x in getattr(instance, f.name).all()])
                                    new = set([str(x) for x in form.cleaned_data[f.name]])
                                    added = new.difference(old)
                                    removed = old.difference(new)
                                    if added or removed:
                                        notify.write("--- {}\n+++ {}\n{}\n{}\n".format(
                                            f.verbose_name,
                                            f.verbose_name,
                                            "\n".join(["+ %s" % a for a in added]),
                                            "\n".join(["- %s" % r for r in removed]),
                                        ))
                    else:
                        # Regular field!
                        # Sometimes it shows up as changed even if it hasn't changed, so do
                        # a second check on if the diff is non-empty.
                        diffrows = [x for x in
                                    difflib.unified_diff(
                                        old_values[f.name].splitlines(),
                                        str(form.cleaned_data[f.name]).splitlines(),
                                        n=1,
                                        lineterm='',
                                        fromfile=f.verbose_name,
                                        tofile=f.verbose_name,
                                    ) if not x.startswith("@@")]
                        if diffrows:
                            notify.write("\n".join(diffrows))
                            notify.write("\n\n")

            if do_notify and notify.tell():
                send_simple_mail(
                    settings.NOTIFICATION_FROM,
                    settings.NOTIFICATION_EMAIL,
                    "%s by %s" % (subj, request.user.username),
                    "Title: {0}\n\n{1}".format(
                        str(instance),
                        notify.getvalue(),
                    ),
                )
            form.save_m2m()

            return HttpResponseRedirect(redirect)
    else:
        # Generate form
        form = formclass(instance=instance)

    if hasattr(form, 'filter_by_user'):
        form.filter_by_user(request.user)

    for fn in form.fields:
        if fn in getattr(instancetype, 'markdown_fields', []):
            form.fields[fn].widget.attrs.update({'class': 'markdown-content'})

    for togg in getattr(form, 'toggle_fields', []):
        form.fields[togg['name']].widget.attrs.update({
            'data-toggles': ','.join(togg['fields']),
            'data-toggle-invert': togg['invert'] and 'true' or 'false',
            'class': 'toggle-checkbox',
        })

    return render_pgweb(request, navsection, formtemplate, {
        'form': form,
        'formitemtype': instance._meta.verbose_name,
        'form_intro': hasattr(form, 'form_intro') and form.form_intro or None,
        'described_checkboxes': getattr(form, 'described_checkboxes', {}),
        'savebutton': (itemid == "new") and "Submit New" or "Save",
        'operation': (itemid == "new") and "New" or "Edit",
    })