Source code for beat.web.common.admin

#!/usr/bin/env python
# vim: set fileencoding=utf-8 :

###############################################################################
#                                                                             #
# Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/           #
# Contact: beat.support@idiap.ch                                              #
#                                                                             #
# This file is part of the beat.web module of the BEAT platform.              #
#                                                                             #
# Commercial License Usage                                                    #
# Licensees holding valid commercial BEAT licenses may use this file in       #
# accordance with the terms contained in a written agreement between you      #
# and Idiap. For further information contact tto@idiap.ch                     #
#                                                                             #
# Alternatively, this file may be used under the terms of the GNU Affero      #
# Public License version 3 as published by the Free Software and appearing    #
# in the file LICENSE.AGPL included in the packaging of this file.            #
# The BEAT platform is distributed in the hope that it will be useful, but    #
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY  #
# or FITNESS FOR A PARTICULAR PURPOSE.                                        #
#                                                                             #
# You should have received a copy of the GNU Affero Public License along      #
# with the BEAT platform. If not, see http://www.gnu.org/licenses/.           #
#                                                                             #
###############################################################################

import logging
from functools import partial

from django.conf import settings
from django.contrib import admin
from django.contrib import messages
from django.contrib.admin import helpers
from django.core.mail import EmailMessage
from django.shortcuts import render
from django.template.loader import render_to_string
from guardian import admin as guardian_admin

from .. import __version__
from ..common.models import Shareable

logger = logging.getLogger(__name__)


[docs]class GuardedModelAdminMixin(guardian_admin.GuardedModelAdminMixin): @property def queryset(self): return partial(self.get_queryset)
[docs]class Django18ProofGuardedModelAdmin(GuardedModelAdminMixin, admin.ModelAdmin): """Extend this class if your model is guarded by Guardian (per-object authorization). This class is a workaround for Django-1.8. See more at issue #307 https://github.com/django-guardian/django-guardian/issues/307 """
[docs]def notify_by_email(attribute=None): """Generates a notify_by_email() admin action. If attribute is set, then, use it as to restrict the number of users the email will be sent to. """ def notify_by_email_inner(modeladmin, request, queryset): """Notifies users by e-mail on admin request""" if "send" in request.POST: # sends the message after user confirmation for instance in queryset: users = instance.users_with_access() if not users: modeladmin.message_user( request, "No users to e-mail for " "'%s'" % instance.fullname(), level=messages.WARNING, ) return # filter users using notification preferences users = [u for u in users if getattr(u.accountsettings, attribute)] if not users: modeladmin.message_user( request, "Affected users for '%s' don't want to be e-mailed" % instance.fullname(), level=messages.WARNING, ) return if instance.sharing == Shareable.PUBLIC: action = "made public" elif instance.sharing == Shareable.SHARED: action = "shared with you (or a team you are in)" else: modeladmin.message_user( request, "'%s' is private. Not e-mailing anyone." % instance.fullname(), level=messages.ERROR, ) return objurl = request.build_absolute_uri(instance.get_absolute_url()) ctx = { "object": instance, "verbose_name": instance._meta.verbose_name, "objurl": objurl, "beat_version": __version__, "action": action, } emails = [u.email for u in users] subj = render_to_string("common/sharing_email_subject.txt", ctx) body = render_to_string("common/sharing_email_body.txt", ctx) mesg = EmailMessage( subj.strip(), body, settings.DEFAULT_FROM_EMAIL, to=[settings.DEFAULT_FROM_EMAIL], bcc=emails, ) plural = "" if len(emails) == 1 else "s" try: mesg.send() except Exception: errormsg = "Could not send e-mails to %d user%s of '%s'" % ( len(emails), plural, instance.fullname(), ) modeladmin.message_user(request, errormsg) import traceback logger.warn( errormsg + ". Exception caught: %s", traceback.format_exc() ) modeladmin.message_user( request, "Successfully notified %d " "user%s of '%s'" % (len(emails), plural, instance.fullname()), ) else: # presents the user with an intermediary page asking to confirm users_per_instance = {} for instance in queryset: users = instance.users_with_access() # filter users using notification preferences users = [u for u in users if getattr(u.accountsettings, attribute)] users_per_instance[instance] = users return render( request, "common/email_confirmation.html", { "users": users_per_instance, "title": "Confirm mass e-mail submission", "queryset": queryset, "action_checkbox_name": helpers.ACTION_CHECKBOX_NAME, }, ) notify_by_email_inner.short_description = "Notify affected users" return notify_by_email_inner