diff --git a/orchestra/contrib/accounts/admin.py b/orchestra/contrib/accounts/admin.py index a046a4a5..2b9a4773 100644 --- a/orchestra/contrib/accounts/admin.py +++ b/orchestra/contrib/accounts/admin.py @@ -216,7 +216,6 @@ class AccountAdminMixin(object): return 'False' % (static('admin/img/inline-delete.svg'), msg) return 'False' % static('admin/img/icon-yes.svg') display_active.short_description = _("active") - display_active.allow_tags = True display_active.admin_order_field = 'is_active' def account_link(self, instance): diff --git a/orchestra/contrib/databases/admin.py b/orchestra/contrib/databases/admin.py index dc56f9db..d50c23d4 100644 --- a/orchestra/contrib/databases/admin.py +++ b/orchestra/contrib/databases/admin.py @@ -1,6 +1,8 @@ from django.conf.urls import url from django.contrib import admin from django.contrib.auth.admin import UserAdmin +from django.utils.html import format_html +from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin @@ -49,17 +51,17 @@ class DatabaseAdmin(SelectAccountAdminMixin, ExtendedModelAdmin): filter_by_account_fields = ('users',) list_prefetch_related = ('users',) actions = (list_accounts, save_selected) - + + @mark_safe def display_users(self, db): links = [] for user in db.users.all(): - link = '%s' % (change_url(user), user.username) + link = format_html('{}', change_url(user), user.username) links.append(link) return '
'.join(links) display_users.short_description = _("Users") - display_users.allow_tags = True display_users.admin_order_field = 'users__username' - + def save_model(self, request, obj, form, change): super(DatabaseAdmin, self).save_model(request, obj, form, change) if not change: @@ -98,24 +100,24 @@ class DatabaseUserAdmin(SelectAccountAdminMixin, ChangePasswordAdminMixin, Exten filter_by_account_fields = ('databases',) list_prefetch_related = ('databases',) actions = (list_accounts, save_selected) - + + @mark_safe def display_databases(self, user): links = [] for db in user.databases.all(): - link = '%s' % (change_url(db), db.name) + link = format_html('{}', change_url(db), db.name) links.append(link) return '
'.join(links) display_databases.short_description = _("Databases") - display_databases.allow_tags = True display_databases.admin_order_field = 'databases__name' - + def get_urls(self): useradmin = UserAdmin(DatabaseUser, self.admin_site) return [ url(r'^(\d+)/password/$', self.admin_site.admin_view(useradmin.user_change_password)) ] + super(DatabaseUserAdmin, self).get_urls() - + def save_model(self, request, obj, form, change): """ set password """ if not change: diff --git a/orchestra/contrib/domains/admin.py b/orchestra/contrib/domains/admin.py index f20849dd..a1dd6141 100644 --- a/orchestra/contrib/domains/admin.py +++ b/orchestra/contrib/domains/admin.py @@ -74,9 +74,8 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin): def structured_name(self, domain): if domain.is_top: return domain.name - return ' '*4 + domain.name + return mark_safe(' '*4 + domain.name) structured_name.short_description = _("name") - structured_name.allow_tags = True structured_name.admin_order_field = 'structured_name' def display_is_top(self, domain): @@ -101,15 +100,14 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin): return '
'.join(links) add_url = reverse('admin:websites_website_add') add_url += '?account=%i&domains=%i' % (domain.account_id, domain.pk) - image = '' % static('orchestra/images/add.png') - add_link = '%s' % ( - add_url, _("Add website"), image + add_link = format_html( + '', add_url, + _("Add website"), static('orchestra/images/add.png'), ) return _("No website %s") % (add_link) return '---' display_websites.admin_order_field = 'websites__name' display_websites.short_description = _("Websites") - display_websites.allow_tags = True @mark_safe def display_addresses(self, domain): @@ -130,10 +128,9 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin): return '---' display_addresses.short_description = _("Addresses") display_addresses.admin_order_field = 'addresses__count' - display_addresses.allow_tags = True + @mark_safe def implicit_records(self, domain): - defaults = [] types = set(domain.records.values_list('type', flat=True)) ttl = settings.DOMAINS_DEFAULT_TTL lines = [] @@ -145,14 +142,13 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin): value=record.value ) if not domain.record_is_implicit(record, types): - line = '%s' % line + line = format_html('{}', line) if record.type is Record.SOA: lines.insert(0, line) else: lines.append(line) return '
'.join(lines) implicit_records.short_description = _("Implicit records") - implicit_records.allow_tags = True def get_fieldsets(self, request, obj=None): """ Add SOA fields when domain is top """ diff --git a/orchestra/contrib/mailboxes/admin.py b/orchestra/contrib/mailboxes/admin.py index 77e549f3..f1b54feb 100644 --- a/orchestra/contrib/mailboxes/admin.py +++ b/orchestra/contrib/mailboxes/admin.py @@ -6,6 +6,7 @@ from django.contrib import admin, messages from django.urls import reverse from django.db.models import F, Count, Value as V from django.db.models.functions import Concat +from django.utils.html import format_html, format_html_join from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ @@ -82,6 +83,7 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo if settings.MAILBOXES_LOCAL_DOMAIN: type(self).actions = self.actions + (SendMailboxEmail(),) + @mark_safe def display_addresses(self, mailbox): # Get from forwards cache = caches.get_request_cache() @@ -93,7 +95,7 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo qs = qs.values_list('id', 'email', 'forward') for addr_id, email, mbox in qs: url = reverse('admin:mailboxes_address_change', args=(addr_id,)) - link = '%s' % (url, email) + link = format_html('{}', url, email) try: cached_forwards[mbox].append(link) except KeyError: @@ -107,26 +109,23 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo addresses = [] for addr in mailbox.addresses.all(): url = change_url(addr) - addresses.append('%s' % (url, addr.email)) + addresses.append(format_html('{}', url, addr.email)) return '
'.join(addresses+forwards) display_addresses.short_description = _("Addresses") - display_addresses.allow_tags = True def display_forwards(self, mailbox): - forwards = [] - for addr in mailbox.get_forwards(): - url = change_url(addr) - forwards.append('%s' % (url, addr.email)) - return '
'.join(forwards) + forwards = mailbox.get_forwards() + return format_html_join( + '
', '{}', + [(change_url(addr), addr.email) for addr in forwards] + ) display_forwards.short_description = _("Forward from") - display_forwards.allow_tags = True + @mark_safe def display_filtering(self, mailbox): - """ becacuse of allow_tags = True """ return mailbox.get_filtering_display() display_filtering.short_description = _("Filtering") display_filtering.admin_order_field = 'filtering' - display_filtering.allow_tags = True def formfield_for_dbfield(self, db_field, **kwargs): if db_field.name == 'filtering': @@ -247,29 +246,27 @@ class AddressAdmin(SelectAccountAdminMixin, ExtendedModelAdmin): def email_link(self, address): link = self.domain_link(address) - return "%s@%s" % (address.name, link) + return format_html("{}@{}", address.name, link) email_link.short_description = _("Email") - email_link.allow_tags = True def display_mailboxes(self, address): - boxes = [] - for mailbox in address.mailboxes.all(): - url = change_url(mailbox) - boxes.append('%s' % (url, mailbox.name)) - return '
'.join(boxes) + boxes = address.mailboxes.all() + return format_html_join( + '
', '{}', + [(change_url(mailbox), mailbox.name) for mailbox in boxes] + ) display_mailboxes.short_description = _("Mailboxes") - display_mailboxes.allow_tags = True display_mailboxes.admin_order_field = 'mailboxes__count' def display_all_mailboxes(self, address): - boxes = [] - for mailbox in address.get_mailboxes(): - url = change_url(mailbox) - boxes.append('%s' % (url, mailbox.name)) - return '
'.join(boxes) + boxes = address.get_mailboxes() + return format_html_join( + '
', '{}', + [(change_url(mailbox), mailbox.name) for mailbox in boxes] + ) display_all_mailboxes.short_description = _("Mailboxes links") - display_all_mailboxes.allow_tags = True + @mark_safe def display_forward(self, address): forward_mailboxes = {m.name: m for m in address.get_forward_mailboxes()} values = [] @@ -281,7 +278,6 @@ class AddressAdmin(SelectAccountAdminMixin, ExtendedModelAdmin): values.append(forward) return '
'.join(values) display_forward.short_description = _("Forward") - display_forward.allow_tags = True display_forward.admin_order_field = 'forward' def formfield_for_dbfield(self, db_field, **kwargs): diff --git a/orchestra/contrib/mailer/admin.py b/orchestra/contrib/mailer/admin.py index 1eaabad0..3e7371d5 100644 --- a/orchestra/contrib/mailer/admin.py +++ b/orchestra/contrib/mailer/admin.py @@ -6,6 +6,8 @@ from django.contrib import admin from django.urls import reverse from django.db.models import Count from django.shortcuts import redirect +from django.utils.html import format_html +from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ from orchestra.admin import ExtendedModelAdmin @@ -60,11 +62,10 @@ class MessageAdmin(ExtendedModelAdmin): def display_subject(self, instance): subject = instance.subject if len(subject) > 64: - return subject[:64] + '…' + return mark_safe(subject[:64] + '…') return subject display_subject.short_description = _("Subject") display_subject.admin_order_field = 'subject' - display_subject.allow_tags = True def display_retries(self, instance): num_logs = instance.logs__count @@ -74,10 +75,9 @@ class MessageAdmin(ExtendedModelAdmin): else: url = reverse('admin:mailer_smtplog_changelist') url += '?&message=%i' % instance.pk - return '%d' % (url, instance.retries) + return format_html('{}', url, instance.retries) display_retries.short_description = _("Retries") display_retries.admin_order_field = 'retries' - display_retries.allow_tags = True def display_content(self, instance): part = email.message_from_string(instance.content) @@ -99,9 +99,8 @@ class MessageAdmin(ExtendedModelAdmin): payload = payload.decode(charset) if part.get_content_type() == 'text/plain': payload = payload.replace('\n', '
').replace(' ', ' ') - return payload + return mark_safe(payload) display_content.short_description = _("Content") - display_content.allow_tags = True def display_full_subject(self, instance): return instance.subject