Compare commits
25 commits
master
...
concat_rib
Author | SHA1 | Date | |
---|---|---|---|
Jorge Pastor | 38d31d42e8 | ||
Jorge Pastor | 7bf7518339 | ||
Jorge Pastor | be039bbeeb | ||
Jorge Pastor | 465862e444 | ||
38a671a18a | |||
bf84b27e8a | |||
a41243bc70 | |||
b2d335879a | |||
87ee955531 | |||
8ff8676773 | |||
f8e20f448c | |||
727e63c9af | |||
9f50bcc672 | |||
8f84b4fee9 | |||
4475b3257e | |||
708bbb3a3f | |||
4368b40d00 | |||
dacc046dc0 | |||
50b83c31bd | |||
24baf1bb70 | |||
7d9805869d | |||
d6c9620b54 | |||
27463807f5 | |||
f63134f3fe | |||
Jorge Pastor | 39eea70b79 |
4
TODO.md
4
TODO.md
|
@ -170,10 +170,10 @@ django-admin.py compilemessages -l ca
|
|||
|
||||
https://docs.djangoproject.com/en/1.7/topics/i18n/translation/#joining-strings-string-concat
|
||||
|
||||
from django.utils.translation import ugettext
|
||||
from django.utils.translation import gettext
|
||||
from django.utils import translation
|
||||
translation.activate('ca')
|
||||
ugettext("Description")
|
||||
gettext("Description")
|
||||
|
||||
* saas validate_creation generic approach, for all backends. standard output
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
```python
|
||||
import os
|
||||
import textwrap
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from orchestra.contrib.orchestration import ServiceController, replace
|
||||
from orchestra.contrib.resources import ServiceMonitor
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ from django.contrib import admin
|
|||
from django.urls import reverse
|
||||
from django.shortcuts import render, redirect
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from .dashboard import *
|
||||
from .options import *
|
||||
|
|
|
@ -3,7 +3,7 @@ from functools import partial
|
|||
from django.contrib import admin
|
||||
from django.core.mail import send_mass_mail
|
||||
from django.shortcuts import render
|
||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||
from django.utils.translation import ngettext, gettext_lazy as _
|
||||
|
||||
from .. import settings
|
||||
|
||||
|
@ -81,7 +81,7 @@ class SendEmail(object):
|
|||
if extra_to:
|
||||
emails.append((subject, message, email_from, extra_to))
|
||||
send_mass_mail(emails, fail_silently=False)
|
||||
msg = ungettext(
|
||||
msg = ngettext(
|
||||
_("Message has been sent to one %s.") % self.opts.verbose_name_plural,
|
||||
_("Message has been sent to %i %s.") % (num, self.opts.verbose_name_plural),
|
||||
num
|
||||
|
@ -124,7 +124,7 @@ def base_disable(modeladmin, request, queryset, disable=True):
|
|||
'verbose_name_plural': opts.verbose_name_plural,
|
||||
'num': num
|
||||
}
|
||||
msg = ungettext(
|
||||
msg = ngettext(
|
||||
_("Selected %(verbose_name)s and related services has been %(action_name)s.") % context,
|
||||
_("%(num)s selected %(verbose_name_plural)s and related services have been %(action_name)s.") % context,
|
||||
num)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from fluent_dashboard import dashboard, appsettings
|
||||
from fluent_dashboard.modules import CmsAppIconList
|
||||
|
||||
|
|
|
@ -4,11 +4,10 @@ from django.contrib import messages
|
|||
from django.contrib.admin import helpers
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.template.response import TemplateResponse
|
||||
from django.utils.decorators import available_attrs
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.html import format_html
|
||||
from django.utils.text import capfirst
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
def admin_field(method):
|
||||
|
@ -50,7 +49,7 @@ def action_with_confirmation(action_name=None, extra_context=None, validator=Non
|
|||
"""
|
||||
|
||||
def decorator(func, extra_context=extra_context, template=template, action_name=action_name, validatior=validator):
|
||||
@wraps(func, assigned=available_attrs(func))
|
||||
@wraps(func)
|
||||
def inner(modeladmin, request, queryset, action_name=action_name, extra_context=extra_context, validator=validator):
|
||||
if validator is not None:
|
||||
try:
|
||||
|
@ -69,10 +68,10 @@ def action_with_confirmation(action_name=None, extra_context=None, validator=Non
|
|||
action_value = func.__name__
|
||||
|
||||
if len(queryset) == 1:
|
||||
objects_name = force_text(opts.verbose_name)
|
||||
objects_name = force_str(opts.verbose_name)
|
||||
obj = queryset.get()
|
||||
else:
|
||||
objects_name = force_text(opts.verbose_name_plural)
|
||||
objects_name = force_str(opts.verbose_name_plural)
|
||||
obj = None
|
||||
if not action_name:
|
||||
action_name = func.__name__
|
||||
|
|
|
@ -5,8 +5,8 @@ from django import forms
|
|||
from django.contrib.admin import helpers
|
||||
from django.core import validators
|
||||
from django.forms.models import modelformset_factory, BaseModelFormSet
|
||||
from django.template import Template
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.template import Template, Context
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.forms.widgets import SpanWidget
|
||||
|
||||
|
@ -31,7 +31,7 @@ class AdminFormMixin(object):
|
|||
context = {
|
||||
'adminform': adminform
|
||||
}
|
||||
return template.render(context)
|
||||
return template.render(Context(context))
|
||||
|
||||
|
||||
class AdminFormSet(BaseModelFormSet):
|
||||
|
@ -74,7 +74,7 @@ class AdminFormSet(BaseModelFormSet):
|
|||
context = {
|
||||
'formset': self
|
||||
}
|
||||
return template.render(context)
|
||||
return template.render(Context(context))
|
||||
|
||||
|
||||
class AdminPasswordChangeForm(forms.Form):
|
||||
|
|
|
@ -3,7 +3,7 @@ from copy import deepcopy
|
|||
from admin_tools.menu import items, Menu
|
||||
from django.urls import reverse
|
||||
from django.utils.text import capfirst
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.core import services, accounts, administration
|
||||
|
||||
|
@ -73,7 +73,7 @@ class OrchestraMenu(Menu):
|
|||
self.children = [
|
||||
# items.MenuItem(
|
||||
# mark_safe('{site_name} <span style="{version_style}">v{version}</span>'.format(
|
||||
# site_name=force_text(settings.SITE_VERBOSE_NAME),
|
||||
# site_name=force_str(settings.SITE_VERBOSE_NAME),
|
||||
# version_style="text-transform:none; float:none; font-size:smaller; background:none;",
|
||||
# version=get_version())),
|
||||
# reverse('admin:index')
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from urllib import parse
|
||||
|
||||
from django import forms
|
||||
from django.conf.urls import url
|
||||
from django.urls import re_path as url
|
||||
from django.contrib import admin, messages
|
||||
from django.contrib.admin.options import IS_POPUP_VAR
|
||||
from django.contrib.admin.utils import unquote
|
||||
|
@ -12,9 +12,9 @@ from django.forms.models import BaseInlineFormSet
|
|||
from django.shortcuts import get_object_or_404
|
||||
from django.template.response import TemplateResponse
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.html import escape
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.decorators.debug import sensitive_post_parameters
|
||||
|
||||
from orchestra.models.utils import has_db_field
|
||||
|
@ -230,7 +230,7 @@ class ExtendedModelAdmin(ChangeViewActionsMixin,
|
|||
if obj is None:
|
||||
opts = self.model._meta
|
||||
raise Http404(_('%(name)s object with primary key %(key)r does not exist.') % {
|
||||
'name': force_text(opts.verbose_name), 'key': escape(object_id)})
|
||||
'name': force_str(opts.verbose_name), 'key': escape(object_id)})
|
||||
return obj
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
from django.contrib.admin.options import get_content_type_for_model
|
||||
from django.conf import settings as django_settings
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.module_loading import autodiscover_modules
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
from rest_framework.routers import DefaultRouter
|
||||
|
||||
from orchestra import settings
|
||||
|
@ -52,7 +52,7 @@ class LogApiMixin(object):
|
|||
user_id=request.user.pk,
|
||||
content_type_id=get_content_type_for_model(instance).pk,
|
||||
object_id=instance.pk,
|
||||
object_repr=force_text(instance),
|
||||
object_repr=force_str(instance),
|
||||
action_flag=action,
|
||||
change_message=message,
|
||||
)
|
||||
|
|
|
@ -3,7 +3,7 @@ import copy
|
|||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.forms import widgets
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
from rest_framework.utils import model_meta
|
||||
|
||||
|
|
|
@ -9,10 +9,10 @@ from django.db import router
|
|||
from django.shortcuts import redirect, render
|
||||
from django.template.response import TemplateResponse
|
||||
from django.utils import timezone
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.html import format_html
|
||||
from django.utils.text import capfirst
|
||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||
from django.utils.translation import ngettext, gettext_lazy as _
|
||||
|
||||
from orchestra.core import services
|
||||
|
||||
|
@ -84,7 +84,7 @@ def delete_related_services(modeladmin, request, queryset):
|
|||
def format(obj, account=False):
|
||||
has_admin = obj.__class__ in admin_site._registry
|
||||
opts = obj._meta
|
||||
no_edit_link = '%s: %s' % (capfirst(opts.verbose_name), force_text(obj))
|
||||
no_edit_link = '%s: %s' % (capfirst(opts.verbose_name), force_str(obj))
|
||||
|
||||
if has_admin:
|
||||
try:
|
||||
|
@ -154,7 +154,7 @@ def delete_related_services(modeladmin, request, queryset):
|
|||
if accounts:
|
||||
relateds = len(to_delete)
|
||||
for obj in to_delete:
|
||||
obj_display = force_text(obj)
|
||||
obj_display = force_str(obj)
|
||||
modeladmin.log_deletion(request, obj, obj_display)
|
||||
obj.delete()
|
||||
context = {
|
||||
|
@ -167,9 +167,9 @@ def delete_related_services(modeladmin, request, queryset):
|
|||
return None
|
||||
|
||||
if len(queryset) == 1:
|
||||
objects_name = force_text(opts.verbose_name)
|
||||
objects_name = force_str(opts.verbose_name)
|
||||
else:
|
||||
objects_name = force_text(opts.verbose_name_plural)
|
||||
objects_name = force_str(opts.verbose_name_plural)
|
||||
|
||||
model_count = {}
|
||||
for model, objs in collector.model_objs.items():
|
||||
|
@ -214,7 +214,7 @@ def disable_selected(modeladmin, request, queryset, disable=True):
|
|||
account.disable() if disable else account.enable()
|
||||
modeladmin.log_change(request, account, verbose_action_name.capitalize())
|
||||
n += 1
|
||||
modeladmin.message_user(request, ungettext(
|
||||
modeladmin.message_user(request, ngettext(
|
||||
_("One account has been successfully %s.") % verbose_action_name,
|
||||
_("%i accounts have been successfully %s.") % (n, verbose_action_name),
|
||||
n)
|
||||
|
@ -227,7 +227,7 @@ def disable_selected(modeladmin, request, queryset, disable=True):
|
|||
def format(obj):
|
||||
has_admin = obj.__class__ in admin_site._registry
|
||||
opts = obj._meta
|
||||
no_edit_link = '%s: %s' % (capfirst(opts.verbose_name), force_text(obj))
|
||||
no_edit_link = '%s: %s' % (capfirst(opts.verbose_name), force_str(obj))
|
||||
if has_admin:
|
||||
try:
|
||||
admin_url = reverse(
|
||||
|
@ -258,9 +258,9 @@ def disable_selected(modeladmin, request, queryset, disable=True):
|
|||
display.append([format(account), current])
|
||||
|
||||
if len(queryset) == 1:
|
||||
objects_name = force_text(opts.verbose_name)
|
||||
objects_name = force_str(opts.verbose_name)
|
||||
else:
|
||||
objects_name = force_text(opts.verbose_name_plural)
|
||||
objects_name = force_str(opts.verbose_name_plural)
|
||||
|
||||
context = dict(
|
||||
admin_site.each_context(request),
|
||||
|
|
|
@ -4,7 +4,7 @@ from urllib.parse import parse_qsl
|
|||
|
||||
from django import forms
|
||||
from django.apps import apps
|
||||
from django.conf.urls import url
|
||||
from django.urls import re_path as url
|
||||
from django.contrib import admin, messages
|
||||
from django.contrib.admin.utils import unquote
|
||||
from django.contrib.auth import admin as auth
|
||||
|
@ -12,7 +12,7 @@ from django.urls import reverse
|
|||
from django.http import HttpResponseRedirect
|
||||
from django.templatetags.static import static
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
|
||||
from orchestra.admin.actions import SendEmail
|
||||
|
@ -26,12 +26,13 @@ from .actions import (list_contacts, service_report, delete_related_services, di
|
|||
enable_selected)
|
||||
from .forms import AccountCreationForm
|
||||
from .models import Account
|
||||
from .filters import HasTipeServerFilter
|
||||
|
||||
|
||||
class AccountAdmin(ChangePasswordAdminMixin, auth.UserAdmin, ExtendedModelAdmin):
|
||||
list_display = ('username', 'full_name', 'type', 'is_active')
|
||||
list_filter = (
|
||||
'type', 'is_active',
|
||||
'type', 'is_active', HasTipeServerFilter
|
||||
)
|
||||
add_fieldsets = (
|
||||
(_("User"), {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import viewsets, exceptions
|
||||
|
||||
from orchestra.api import router, SetPasswordApiMixin, LogApiMixin
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.apps import AppConfig
|
||||
from django.db.models.signals import post_migrate
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.core import services, accounts
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
from django.contrib.admin import SimpleListFilter
|
||||
from django.db.models import Q
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from orchestra.contrib.orchestration.models import Server
|
||||
from orchestra.contrib.websites.models import Website
|
||||
from orchestra.settings import WEB_SERVERS
|
||||
|
||||
class IsActiveListFilter(SimpleListFilter):
|
||||
title = _("is active")
|
||||
|
@ -25,3 +27,16 @@ class IsActiveListFilter(SimpleListFilter):
|
|||
elif self.value() == 'object':
|
||||
return queryset.filter(is_active=False)
|
||||
return queryset
|
||||
|
||||
class HasTipeServerFilter(SimpleListFilter):
|
||||
title = _("has type server")
|
||||
parameter_name = 'has_servers'
|
||||
|
||||
def lookups(self, request, model_admin):
|
||||
return [ (x.id, x.name) for x in Server.objects.filter(name__in=WEB_SERVERS) ]
|
||||
|
||||
def queryset(self, request, queryset):
|
||||
if self.value() is not None:
|
||||
serverWebsites = Website.objects.filter(target_server=self.value())
|
||||
return queryset.filter(id__in=[ x.account.id for x in serverWebsites ] )
|
||||
return queryset
|
|
@ -4,7 +4,7 @@ from collections import OrderedDict
|
|||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.apps import apps
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.forms import UserCreationForm
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ from django.db import models
|
|||
from django.db.models import signals
|
||||
from django.apps import apps
|
||||
from django.utils import timezone, translation
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
#from orchestra.contrib.orchestration.middlewares import OperationsMiddleware
|
||||
#from orchestra.contrib.orchestration import Operation
|
||||
|
@ -165,7 +165,6 @@ class Account(auth.AbstractBaseUser):
|
|||
elif obj and getattr(obj, 'account', None) == self:
|
||||
return True
|
||||
|
||||
|
||||
def has_perms(self, perm_list, obj=None):
|
||||
"""
|
||||
Returns True if the user has each of the specified permissions. If
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.contrib.settings import Setting
|
||||
from orchestra.settings import ORCHESTRA_BASE_DOMAIN
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{% extends "orchestra/admin/change_form.html" %}
|
||||
{% load i18n admin_urls admin_static admin_modify %}
|
||||
{% load i18n admin_urls static admin_modify %}
|
||||
|
||||
|
||||
{% block breadcrumbs %}
|
||||
|
|
|
@ -12,7 +12,7 @@ from django.http import HttpResponse, HttpResponseRedirect
|
|||
from django.shortcuts import render, redirect
|
||||
from django.utils import translation, timezone
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||
from django.utils.translation import ngettext, gettext_lazy as _
|
||||
|
||||
from orchestra.admin.decorators import action_with_confirmation
|
||||
from orchestra.admin.forms import AdminFormSet
|
||||
|
@ -69,7 +69,7 @@ def close_bills(modeladmin, request, queryset, action='close_bills'):
|
|||
'url': url,
|
||||
'num': num,
|
||||
}
|
||||
message = ungettext(
|
||||
message = ngettext(
|
||||
_('<a href="%(url)s">One related transaction</a> has been created') % context,
|
||||
_('<a href="%(url)s">%(num)i related transactions</a> have been created') % context,
|
||||
num)
|
||||
|
@ -111,7 +111,7 @@ def send_bills_action(modeladmin, request, queryset):
|
|||
bill.send()
|
||||
modeladmin.log_change(request, bill, 'Sent')
|
||||
num += 1
|
||||
messages.success(request, ungettext(
|
||||
messages.success(request, ngettext(
|
||||
_("One bill has been sent."),
|
||||
_("%i bills have been sent.") % num,
|
||||
num))
|
||||
|
@ -135,7 +135,7 @@ def download_bills(modeladmin, request, queryset):
|
|||
pdf = bill.as_pdf()
|
||||
archive.writestr('%s.pdf' % bill.number, pdf)
|
||||
archive.close()
|
||||
response = HttpResponse(bytesio.getvalue(), content_type='application/pdf')
|
||||
response = HttpResponse(bytesio.getvalue(), content_type='application/zip')
|
||||
response['Content-Disposition'] = 'attachment; filename="orchestra-bills.zip"'
|
||||
return response
|
||||
bill = queryset[0]
|
||||
|
@ -299,7 +299,7 @@ def amend_bills(modeladmin, request, queryset):
|
|||
'url': amend_url,
|
||||
'num': num,
|
||||
}
|
||||
messages.success(request, mark_safe(ungettext(
|
||||
messages.success(request, mark_safe(ngettext(
|
||||
_('<a href="%(url)s">One amendment bill</a> have been generated.') % context,
|
||||
_('<a href="%(url)s">%(num)i amendment bills</a> have been generated.') % context,
|
||||
num
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django import forms
|
||||
from django.conf.urls import url
|
||||
from django.urls import re_path as url
|
||||
from django.contrib import admin, messages
|
||||
from django.contrib.admin.utils import unquote
|
||||
from django.urls import reverse
|
||||
|
@ -9,7 +9,7 @@ from django.db.models.functions import Coalesce
|
|||
from django.templatetags.static import static
|
||||
from django.utils.html import format_html
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.shortcuts import redirect
|
||||
|
||||
from orchestra.admin import ExtendedModelAdmin
|
||||
|
@ -126,7 +126,7 @@ class ClosedBillLineInline(BillLineInline):
|
|||
return line.compute_total()
|
||||
display_total.short_description = _("Total")
|
||||
|
||||
def has_add_permission(self, request):
|
||||
def has_add_permission(self, request, obj):
|
||||
return False
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ from django.contrib.admin import SimpleListFilter
|
|||
from django.urls import reverse
|
||||
from django.db.models import Q
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from . models import Bill
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.admin.utils import admin_link
|
||||
from orchestra.forms import SpanWidget
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
from django.contrib import messages
|
||||
from django.urls import reverse
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.html import format_html
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.text import capfirst
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.admin.utils import change_url
|
||||
|
||||
|
@ -16,14 +16,14 @@ def validate_contact(request, bill, error=True):
|
|||
valid = True
|
||||
send = messages.error if error else messages.warning
|
||||
if not hasattr(bill.account, 'billcontact'):
|
||||
account = force_text(bill.account)
|
||||
account = force_str(bill.account)
|
||||
url = reverse('admin:accounts_account_change', args=(bill.account_id,))
|
||||
message = msg.format(relation=_("Related"), account=account, url=url)
|
||||
send(request, mark_safe(message))
|
||||
valid = False
|
||||
main = type(bill).account.field.related_model.objects.get_main()
|
||||
if not hasattr(main, 'billcontact'):
|
||||
account = force_text(main)
|
||||
account = force_str(main)
|
||||
url = reverse('admin:accounts_account_change', args=(main.id,))
|
||||
message = msg.format(relation=_("Main"), account=account, url=url)
|
||||
send(request, mark_safe(message))
|
||||
|
|
|
@ -8,9 +8,9 @@ from django.db.models import F, Sum
|
|||
from django.db.models.functions import Coalesce
|
||||
from django.template import loader
|
||||
from django.utils import timezone, translation
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.admin.utils import change_url
|
||||
from orchestra.contrib.accounts.models import Account
|
||||
|
@ -209,7 +209,7 @@ class Bill(models.Model):
|
|||
|
||||
def get_payment_state_display(self):
|
||||
value = self.payment_state
|
||||
return force_text(dict(self.PAYMENT_STATES).get(value, value))
|
||||
return force_str(dict(self.PAYMENT_STATES).get(value, value))
|
||||
|
||||
def get_current_transaction(self):
|
||||
return self.transactions.exclude_rejected().first()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django import forms
|
||||
from django.contrib import admin
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.admin import AtLeastOneRequiredInlineFormSet, ExtendedModelAdmin
|
||||
from orchestra.admin.actions import SendEmail
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django.contrib.admin import SimpleListFilter
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from .models import Contact
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import RegexValidator
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.core import validators
|
||||
from orchestra.models.fields import MultiSelectField
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
from django.conf.urls import url
|
||||
from django.urls import re_path as 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 django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
|
||||
from orchestra.admin.utils import change_url
|
||||
|
@ -11,7 +11,7 @@ from orchestra.contrib.accounts.actions import list_accounts
|
|||
from orchestra.contrib.accounts.admin import SelectAccountAdminMixin
|
||||
|
||||
from .filters import HasUserListFilter, HasDatabaseListFilter
|
||||
from .forms import DatabaseCreationForm, DatabaseUserChangeForm, DatabaseUserCreationForm
|
||||
from .forms import DatabaseCreationForm, DatabaseUserChangeForm, DatabaseUserCreationForm, DatabaseForm
|
||||
from .models import Database, DatabaseUser
|
||||
|
||||
def save_selected(modeladmin, request, queryset):
|
||||
|
@ -20,21 +20,21 @@ def save_selected(modeladmin, request, queryset):
|
|||
save_selected.short_description = "Re-save selected objects"
|
||||
|
||||
class DatabaseAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||
list_display = ('name', 'type', 'display_users', 'account_link')
|
||||
list_display = ('name', 'type', 'target_server', 'display_users', 'account_link')
|
||||
list_filter = ('type', HasUserListFilter)
|
||||
search_fields = ('name', 'account__username')
|
||||
change_readonly_fields = ('name', 'type')
|
||||
change_readonly_fields = ('name', 'type', 'target_server')
|
||||
extra = 1
|
||||
fieldsets = (
|
||||
(None, {
|
||||
'classes': ('extrapretty',),
|
||||
'fields': ('account_link', 'name', 'type', 'users', 'display_users', 'comments'),
|
||||
'fields': ('account_link', 'name', 'type', 'users', 'display_users', 'comments', 'target_server'),
|
||||
}),
|
||||
)
|
||||
add_fieldsets = (
|
||||
(None, {
|
||||
'classes': ('wide',),
|
||||
'fields': ('account_link', 'name', 'type')
|
||||
'fields': ('account_link', 'name', 'type', 'target_server')
|
||||
}),
|
||||
(_("Create new user"), {
|
||||
'classes': ('wide',),
|
||||
|
@ -45,11 +45,10 @@ class DatabaseAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
|||
'fields': ('user',)
|
||||
}),
|
||||
)
|
||||
form = DatabaseForm
|
||||
add_form = DatabaseCreationForm
|
||||
readonly_fields = ('account_link', 'display_users',)
|
||||
filter_horizontal = ['users']
|
||||
filter_by_account_fields = ('users',)
|
||||
list_prefetch_related = ('users',)
|
||||
actions = (list_accounts, save_selected)
|
||||
|
||||
@mark_safe
|
||||
|
@ -71,6 +70,7 @@ class DatabaseAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
|||
username=form.cleaned_data['username'],
|
||||
type=obj.type,
|
||||
account_id=obj.account.pk,
|
||||
target_server=form.cleaned_data['target_server'],
|
||||
)
|
||||
user.set_password(form.cleaned_data["password1"])
|
||||
user.save()
|
||||
|
@ -78,22 +78,22 @@ class DatabaseAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
|||
|
||||
|
||||
class DatabaseUserAdmin(SelectAccountAdminMixin, ChangePasswordAdminMixin, ExtendedModelAdmin):
|
||||
list_display = ('username', 'type', 'display_databases', 'account_link')
|
||||
list_display = ('username', 'target_server', 'type', 'display_databases', 'account_link')
|
||||
list_filter = ('type', HasDatabaseListFilter)
|
||||
search_fields = ('username', 'account__username')
|
||||
form = DatabaseUserChangeForm
|
||||
add_form = DatabaseUserCreationForm
|
||||
change_readonly_fields = ('username', 'type')
|
||||
change_readonly_fields = ('username', 'type', 'target_server')
|
||||
fieldsets = (
|
||||
(None, {
|
||||
'classes': ('extrapretty',),
|
||||
'fields': ('account_link', 'username', 'password', 'type', 'display_databases')
|
||||
'fields': ('account_link', 'username', 'password', 'type', 'display_databases', 'target_server', 'permision')
|
||||
}),
|
||||
)
|
||||
add_fieldsets = (
|
||||
(None, {
|
||||
'classes': ('extrapretty',),
|
||||
'fields': ('account_link', 'username', 'password1', 'password2', 'type')
|
||||
'fields': ('account_link', 'username', 'password1', 'password2', 'type', 'target_server', 'permision')
|
||||
}),
|
||||
)
|
||||
readonly_fields = ('account_link', 'display_databases',)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django.apps import AppConfig
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.core import services
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import textwrap
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.contrib.orchestration import ServiceController, replace
|
||||
from orchestra.contrib.resources import ServiceMonitor
|
||||
|
@ -36,6 +36,12 @@ class MySQLController(ServiceController):
|
|||
'username': user.username,
|
||||
'grant': 'WITH GRANT OPTION' if user == context['owner'] else ''
|
||||
})
|
||||
if user.permision == "ro":
|
||||
self.append(textwrap.dedent("""\
|
||||
mysql -e 'GRANT SELECT ON `%(database)s`.* TO "%(username)s"@"%(host)s" %(grant)s;'\
|
||||
""") % context
|
||||
)
|
||||
else:
|
||||
self.append(textwrap.dedent("""\
|
||||
mysql -e 'GRANT ALL PRIVILEGES ON `%(database)s`.* TO "%(username)s"@"%(host)s" %(grant)s;'\
|
||||
""") % context
|
||||
|
@ -85,8 +91,8 @@ class MySQLUserController(ServiceController):
|
|||
context = self.get_context(user)
|
||||
self.append(textwrap.dedent("""\
|
||||
# Create user %(username)s
|
||||
mysql -e 'CREATE USER "%(username)s"@"%(host)s";' || true # User already exists
|
||||
mysql -e 'UPDATE mysql.user SET Password="%(password)s" WHERE User="%(username)s";'\
|
||||
mysql -e 'CREATE USER IF NOT EXISTS "%(username)s"@"%(host)s";'
|
||||
mysql -e 'ALTER USER IF EXISTS "%(username)s"@"%(host)s" IDENTIFIED BY PASSWORD "%(password)s";'\
|
||||
""") % context
|
||||
)
|
||||
|
||||
|
@ -172,7 +178,7 @@ class MysqlDisk(ServiceMonitor):
|
|||
def get_context(self, db):
|
||||
context = {
|
||||
'db_name': db.name,
|
||||
'db_dirname': db.name.replace('-', '@003f'),
|
||||
'db_dirname': db.name.replace('-', '@002d'),
|
||||
'db_id': db.pk,
|
||||
'db_type': db.type,
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django.contrib.admin import SimpleListFilter
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class HasUserListFilter(SimpleListFilter):
|
||||
|
|
|
@ -3,7 +3,7 @@ from django.contrib.auth.forms import ReadOnlyPasswordHashField
|
|||
from django.core.exceptions import ValidationError
|
||||
from django.utils.html import format_html
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.core import validators
|
||||
|
||||
|
@ -31,13 +31,39 @@ class DatabaseUserCreationForm(forms.ModelForm):
|
|||
return password2
|
||||
|
||||
|
||||
class DatabaseForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = Database
|
||||
fields = ('name', 'users', 'type', 'account', 'target_server')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(DatabaseForm, self).__init__(*args, **kwargs)
|
||||
# muestra solo los usuarios del mismo server
|
||||
account_id = self.instance.account_id
|
||||
database_server_id = self.instance.target_server_id
|
||||
if account_id:
|
||||
self.fields['users'].queryset = DatabaseUser.objects.filter(account=account_id, target_server=database_server_id)
|
||||
|
||||
def clean(self):
|
||||
# verifica que los usuarios petenecen al servidor de la bbdd
|
||||
database_server_id = self.instance.target_server_id
|
||||
users = self.cleaned_data.get('users')
|
||||
if users and database_server_id:
|
||||
for user in users:
|
||||
if user.target_server_id != database_server_id:
|
||||
self.add_error("users", _(f"{user.username} does not belong to the database server"))
|
||||
|
||||
return self.cleaned_data
|
||||
|
||||
|
||||
class DatabaseCreationForm(DatabaseUserCreationForm):
|
||||
username = forms.CharField(label=_("Username"), max_length=16,
|
||||
username = forms.CharField(label=_("Username"), max_length=32,
|
||||
required=False, validators=[validators.validate_name],
|
||||
help_text=_("Required. 16 characters or fewer. Letters, digits and "
|
||||
help_text=_("Required. 32 characters or fewer. Letters, digits and "
|
||||
"@/./+/-/_ only."),
|
||||
error_messages={
|
||||
'invalid': _("This value may contain 16 characters or fewer, only letters, numbers and "
|
||||
'invalid': _("This value may contain 32 characters or fewer, only letters, numbers and "
|
||||
"@/./+/-/_ characters.")})
|
||||
user = forms.ModelChoiceField(required=False, queryset=DatabaseUser.objects)
|
||||
|
||||
|
@ -50,13 +76,14 @@ class DatabaseCreationForm(DatabaseUserCreationForm):
|
|||
account_id = self.initial.get('account', self.initial_account)
|
||||
if account_id:
|
||||
qs = self.fields['user'].queryset.filter(account=account_id).order_by('username')
|
||||
choices = [ (u.pk, "%s (%s)" % (u, u.get_type_display())) for u in qs ]
|
||||
choices = [ (u.pk, "%s (%s) (%s)" % (u, u.get_type_display(), str(u.target_server.name) )) for u in qs ]
|
||||
self.fields['user'].queryset = qs
|
||||
self.fields['user'].choices = [(None, '--------'),] + choices
|
||||
|
||||
def clean_username(self):
|
||||
username = self.cleaned_data.get('username')
|
||||
if DatabaseUser.objects.filter(username=username).exists():
|
||||
server = self.cleaned_data.get('target_server')
|
||||
if DatabaseUser.objects.filter(username=username, target_server=server).exists():
|
||||
raise ValidationError("Provided username already exists.")
|
||||
return username
|
||||
|
||||
|
@ -76,6 +103,9 @@ class DatabaseCreationForm(DatabaseUserCreationForm):
|
|||
if user and user.type != self.cleaned_data.get('type'):
|
||||
msg = _("Database type and user type doesn't match")
|
||||
raise ValidationError(msg)
|
||||
if user and user.target_server != self.cleaned_data.get('target_server'):
|
||||
msg = _("Database server and user server doesn't match")
|
||||
raise ValidationError(msg)
|
||||
return user
|
||||
|
||||
def clean(self):
|
||||
|
|
|
@ -1,52 +1,46 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
# Generated by Django 2.2.28 on 2023-06-28 17:06
|
||||
|
||||
from django.db import models, migrations
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import orchestra.core.validators
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Database',
|
||||
fields=[
|
||||
('id', models.AutoField(serialize=False, primary_key=True, verbose_name='ID', auto_created=True)),
|
||||
('name', models.CharField(verbose_name='name', max_length=64, validators=[orchestra.core.validators.validate_name])),
|
||||
('type', models.CharField(default='mysql', choices=[('mysql', 'MySQL'), ('postgres', 'PostgreSQL')], verbose_name='type', max_length=32)),
|
||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='databases', verbose_name='Account', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='DatabaseUser',
|
||||
fields=[
|
||||
('id', models.AutoField(serialize=False, primary_key=True, verbose_name='ID', auto_created=True)),
|
||||
('username', models.CharField(verbose_name='username', max_length=16, validators=[orchestra.core.validators.validate_name])),
|
||||
('password', models.CharField(verbose_name='password', max_length=256)),
|
||||
('type', models.CharField(default='mysql', choices=[('mysql', 'MySQL'), ('postgres', 'PostgreSQL')], verbose_name='type', max_length=32)),
|
||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='databaseusers', verbose_name='Account', to=settings.AUTH_USER_MODEL)),
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('username', models.CharField(max_length=16, validators=[orchestra.core.validators.validate_name], verbose_name='username')),
|
||||
('password', models.CharField(max_length=256, verbose_name='password')),
|
||||
('type', models.CharField(choices=[('mysql', 'MySQL')], default='mysql', max_length=32, verbose_name='type')),
|
||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='databaseusers', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
|
||||
],
|
||||
options={
|
||||
'verbose_name_plural': 'DB users',
|
||||
'unique_together': {('username', 'type')},
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='database',
|
||||
name='users',
|
||||
field=models.ManyToManyField(related_name='databases', to='databases.DatabaseUser', verbose_name='users', blank=True),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='databaseuser',
|
||||
unique_together=set([('username', 'type')]),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='database',
|
||||
unique_together=set([('name', 'type')]),
|
||||
migrations.CreateModel(
|
||||
name='Database',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=64, validators=[orchestra.core.validators.validate_name], verbose_name='name')),
|
||||
('type', models.CharField(choices=[('mysql', 'MySQL')], default='mysql', max_length=32, verbose_name='type')),
|
||||
('comments', models.TextField(blank=True, default='')),
|
||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='databases', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
|
||||
('users', models.ManyToManyField(blank=True, related_name='databases', to='databases.DatabaseUser', verbose_name='users')),
|
||||
],
|
||||
options={
|
||||
'unique_together': {('name', 'type')},
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# Generated by Django 2.2.28 on 2023-06-28 17:11
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('orchestration', '__first__'),
|
||||
('databases', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='databaseuser',
|
||||
name='target_server',
|
||||
field=models.ForeignKey(default=3, on_delete=django.db.models.deletion.CASCADE, to='orchestration.Server', verbose_name='Target Server'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,29 @@
|
|||
# Generated by Django 2.2.28 on 2023-06-29 16:38
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('orchestration', '__first__'),
|
||||
('databases', '0002_databaseuser_target_server'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='databaseuser',
|
||||
name='permision',
|
||||
field=models.CharField(choices=[('all', 'all'), ('ro', 'read only')], default='all', max_length=20, verbose_name='Permisson'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='databaseuser',
|
||||
name='target_server',
|
||||
field=models.ForeignKey(default=3, on_delete=django.db.models.deletion.CASCADE, to='orchestration.Server', verbose_name='Server'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='databaseuser',
|
||||
unique_together={('username', 'type', 'target_server')},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,20 @@
|
|||
# Generated by Django 2.2.28 on 2023-06-29 16:57
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('orchestration', '__first__'),
|
||||
('databases', '0003_auto_20230629_1838'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='database',
|
||||
name='target_server',
|
||||
field=models.ForeignKey(default=3, on_delete=django.db.models.deletion.CASCADE, to='orchestration.Server', verbose_name='Server'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 2.2.28 on 2023-07-05 10:08
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('orchestration', '__first__'),
|
||||
('databases', '0004_database_target_server'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterUniqueTogether(
|
||||
name='database',
|
||||
unique_together={('name', 'type', 'target_server')},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 2.2.28 on 2023-07-05 10:37
|
||||
|
||||
from django.db import migrations, models
|
||||
import orchestra.core.validators
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('databases', '0005_auto_20230705_1208'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='databaseuser',
|
||||
name='username',
|
||||
field=models.CharField(max_length=32, validators=[orchestra.core.validators.validate_name], verbose_name='username'),
|
||||
),
|
||||
]
|
|
@ -1,7 +1,7 @@
|
|||
import hashlib
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.core import validators
|
||||
|
||||
|
@ -23,9 +23,11 @@ class Database(models.Model):
|
|||
account = models.ForeignKey('accounts.Account', on_delete=models.CASCADE,
|
||||
verbose_name=_("Account"), related_name='databases')
|
||||
comments = models.TextField(default="", blank=True)
|
||||
target_server = models.ForeignKey('orchestration.Server', on_delete=models.CASCADE,
|
||||
verbose_name=_("Server"), default=3 )
|
||||
|
||||
class Meta:
|
||||
unique_together = ('name', 'type')
|
||||
unique_together = ('name', 'type', 'target_server')
|
||||
|
||||
def __str__(self):
|
||||
return "%s" % self.name
|
||||
|
@ -54,7 +56,12 @@ class DatabaseUser(models.Model):
|
|||
MYSQL = Database.MYSQL
|
||||
POSTGRESQL = Database.POSTGRESQL
|
||||
|
||||
username = models.CharField(_("username"), max_length=16, # MySQL usernames 16 char long
|
||||
typeOfPermision = [
|
||||
('all','all'),
|
||||
('ro', 'read only'),
|
||||
]
|
||||
|
||||
username = models.CharField(_("username"), max_length=32, # MySQL usernames 16 char long
|
||||
validators=[validators.validate_name])
|
||||
password = models.CharField(_("password"), max_length=256)
|
||||
type = models.CharField(_("type"), max_length=32,
|
||||
|
@ -62,10 +69,14 @@ class DatabaseUser(models.Model):
|
|||
default=settings.DATABASES_DEFAULT_TYPE)
|
||||
account = models.ForeignKey('accounts.Account', on_delete=models.CASCADE,
|
||||
verbose_name=_("Account"), related_name='databaseusers')
|
||||
target_server = models.ForeignKey('orchestration.Server', on_delete=models.CASCADE,
|
||||
verbose_name=_("Server"), default=3 )
|
||||
permision = models.CharField(verbose_name=_("Permisson"), max_length=20, choices=typeOfPermision, default='all')
|
||||
|
||||
|
||||
class Meta:
|
||||
verbose_name_plural = _("DB users")
|
||||
unique_together = ('username', 'type')
|
||||
unique_together = ('username', 'type', 'target_server')
|
||||
|
||||
def __str__(self):
|
||||
return self.username
|
||||
|
|
|
@ -7,7 +7,7 @@ from django.db.models.functions import Concat, Coalesce
|
|||
from django.forms.models import modelformset_factory
|
||||
from django.shortcuts import render
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||
from django.utils.translation import ngettext, gettext_lazy as _
|
||||
from django.template.response import TemplateResponse
|
||||
|
||||
from orchestra.admin.utils import get_object_from_url, change_url, admin_link
|
||||
|
@ -84,7 +84,7 @@ def edit_records(modeladmin, request, queryset):
|
|||
change_message = modeladmin.construct_change_message(request, fake_form, [formset])
|
||||
modeladmin.log_change(request, formset.instance, change_message)
|
||||
num = len(formsets)
|
||||
message = ungettext(
|
||||
message = ngettext(
|
||||
_("Records for one selected domain have been updated."),
|
||||
_("Records for %i selected domains have been updated.") % num,
|
||||
num)
|
||||
|
@ -127,7 +127,7 @@ def set_soa(modeladmin, request, queryset):
|
|||
modeladmin.log_change(request, domain, change_message)
|
||||
domain.save()
|
||||
num = len(queryset)
|
||||
msg = ungettext(
|
||||
msg = ngettext(
|
||||
_("SOA record for one domain has been updated."),
|
||||
_("SOA record for %s domains has been updated.") % num,
|
||||
num
|
||||
|
|
|
@ -5,7 +5,7 @@ from django.db.models.functions import Concat, Coalesce
|
|||
from django.templatetags.static import static
|
||||
from django.utils.html import format_html
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext, ugettext_lazy as _
|
||||
from django.utils.translation import gettext, gettext_lazy as _
|
||||
|
||||
from orchestra.admin import ExtendedModelAdmin
|
||||
from orchestra.admin.utils import admin_link, change_url
|
||||
|
|
|
@ -2,7 +2,7 @@ import re
|
|||
import socket
|
||||
import textwrap
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.contrib.orchestration import ServiceController
|
||||
from orchestra.contrib.orchestration import Operation
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django.contrib.admin import SimpleListFilter
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class TopDomainListFilter(SimpleListFilter):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.text import capfirst
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.admin.forms import AdminFormSet, AdminFormMixin
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||
from django.utils.translation import ngettext, gettext_lazy as _
|
||||
|
||||
from orchestra.core.validators import validate_ipv4_address, validate_ipv6_address, validate_ascii
|
||||
from orchestra.utils.python import AttrDict
|
||||
|
@ -114,7 +114,7 @@ class Domain(models.Model):
|
|||
def get_description(self):
|
||||
if self.is_top:
|
||||
num = self.subdomains.count()
|
||||
return ungettext(
|
||||
return ngettext(
|
||||
_("top domain with one subdomain"),
|
||||
_("top domain with %d subdomains") % num,
|
||||
num)
|
||||
|
@ -144,6 +144,10 @@ class Domain(models.Model):
|
|||
tail.append(subdomain)
|
||||
else:
|
||||
zone += subdomain.render_records()
|
||||
###darmengo 2021-03-25 add autoconfig
|
||||
if self.has_default_mx():
|
||||
zone += 'autoconfig.{}. 30m IN A 109.69.8.133\n'.format(self.name)
|
||||
###END darmengo 2021-03-25 add autoconfig
|
||||
for subdomain in sorted(tail, key=lambda x: len(x.name), reverse=True):
|
||||
zone += subdomain.render_records()
|
||||
return zone.strip()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from orchestra.api.serializers import HyperlinkedModelSerializer
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{% extends "admin/change_form.html" %}
|
||||
{% load i18n admin_urls admin_static admin_modify %}
|
||||
{% load i18n admin_urls static admin_modify %}
|
||||
|
||||
|
||||
{% block object-tools-items %}
|
||||
|
|
|
@ -3,7 +3,7 @@ import os
|
|||
import re
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.core.validators import validate_hostname
|
||||
from orchestra.utils import paths
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
from django.contrib import admin
|
||||
from django.contrib.admin.templatetags.admin_static import static
|
||||
from django.templatetags.static import static
|
||||
from django.contrib.admin.templatetags.admin_urls import add_preserved_filters
|
||||
from django.contrib.admin.utils import unquote
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.urls import NoReverseMatch, reverse
|
||||
from django.utils.html import format_html
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.admin.utils import admin_date, admin_link
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import sys
|
|||
|
||||
from django.contrib import messages
|
||||
from django.db import transaction
|
||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||
from django.utils.translation import ngettext, gettext_lazy as _
|
||||
|
||||
from orchestra.admin.decorators import action_with_confirmation
|
||||
|
||||
|
@ -102,7 +102,7 @@ def mark_as_unread(modeladmin, request, queryset):
|
|||
ticket.mark_as_unread_by(request.user)
|
||||
modeladmin.log_change(request, ticket, 'Marked as unread')
|
||||
num = len(queryset)
|
||||
msg = ungettext(
|
||||
msg = ngettext(
|
||||
_("Selected ticket has been marked as unread."),
|
||||
_("%i selected tickets have been marked as unread.") % num,
|
||||
num)
|
||||
|
@ -116,7 +116,7 @@ def mark_as_read(modeladmin, request, queryset):
|
|||
ticket.mark_as_read_by(request.user)
|
||||
modeladmin.log_change(request, ticket, 'Marked as read')
|
||||
num = len(queryset)
|
||||
msg = ungettext(
|
||||
msg = ngettext(
|
||||
_("Selected ticket has been marked as read."),
|
||||
_("%i selected tickets have been marked as read.") % num,
|
||||
num)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django import forms
|
||||
from django.conf.urls import url
|
||||
from django.urls import re_path as url
|
||||
from django.contrib import admin
|
||||
from django.urls import reverse
|
||||
from django.db import models
|
||||
|
@ -7,7 +7,7 @@ from django.http import HttpResponse
|
|||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.html import format_html, strip_tags
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from markdown import markdown
|
||||
|
||||
from orchestra.admin import ExtendedModelAdmin
|
||||
|
@ -68,7 +68,7 @@ class MessageReadOnlyInline(admin.TabularInline):
|
|||
return header + content
|
||||
content_html.short_description = _("Content")
|
||||
|
||||
def has_add_permission(self, request):
|
||||
def has_add_permission(self, request, obj):
|
||||
return False
|
||||
|
||||
def has_delete_permission(self, request, obj=None):
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django.contrib.admin import SimpleListFilter
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from .models import Ticket
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ from django import forms
|
|||
from django.contrib.auth import get_user_model
|
||||
from django.utils.html import strip_tags
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.templatetags.static import static
|
||||
from markdown import markdown
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.conf import settings as djsettings
|
||||
from django.db import models
|
||||
from django.db.models import query, Q
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.contrib.contacts import settings as contacts_settings
|
||||
from orchestra.contrib.contacts.models import Contact
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.contrib import messages, admin
|
||||
from django.template.response import TemplateResponse
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ungettext, ugettext, ugettext_lazy as _
|
||||
from django.utils.translation import ngettext, gettext, gettext_lazy as _
|
||||
|
||||
from orchestra.admin.utils import admin_link
|
||||
from orchestra.contrib.orchestration import Operation, helpers
|
||||
|
@ -16,12 +16,12 @@ def letsencrypt(modeladmin, request, queryset):
|
|||
content_error = ''
|
||||
contentless = queryset.exclude(content__path='/').distinct()
|
||||
if contentless:
|
||||
content_error = ungettext(
|
||||
ugettext("Selected website %s doesn't have a webapp mounted on <tt>/</tt>."),
|
||||
ugettext("Selected websites %s don't have a webapp mounted on <tt>/</tt>."),
|
||||
content_error = ngettext(
|
||||
gettext("Selected website %s doesn't have a webapp mounted on <tt>/</tt>."),
|
||||
gettext("Selected websites %s don't have a webapp mounted on <tt>/</tt>."),
|
||||
len(contentless),
|
||||
)
|
||||
content_error += ugettext("<br>Websites need a webapp (e.g. static) mounted on </tt>/</tt> "
|
||||
content_error += gettext("<br>Websites need a webapp (e.g. static) mounted on </tt>/</tt> "
|
||||
"for let's encrypt HTTP-01 challenge to work.")
|
||||
content_error = content_error % ', '.join((admin_link()(website) for website in contentless))
|
||||
content_error = '<ul class="errorlist"><li>%s</li></ul>' % content_error
|
||||
|
@ -76,19 +76,19 @@ def letsencrypt(modeladmin, request, queryset):
|
|||
'no_https': no_https
|
||||
}
|
||||
if errors:
|
||||
msg = ungettext(
|
||||
msg = ngettext(
|
||||
_("No lineages found for websites {name}."),
|
||||
_("No lineages found for {errors} websites."),
|
||||
errors)
|
||||
messages.error(request, msg % context)
|
||||
if successes:
|
||||
msg = ungettext(
|
||||
msg = ngettext(
|
||||
_("{name} website has successfully been encrypted."),
|
||||
_("{successes} websites have been successfully encrypted."),
|
||||
successes)
|
||||
messages.success(request, msg.format(**context))
|
||||
if no_https:
|
||||
msg = ungettext(
|
||||
msg = ngettext(
|
||||
_("{name} website does not have <b>HTTPS protocol</b> enabled."),
|
||||
_("{no_https} websites do not have <b>HTTPS protocol</b> enabled."),
|
||||
no_https)
|
||||
|
@ -99,7 +99,7 @@ def letsencrypt(modeladmin, request, queryset):
|
|||
context = {
|
||||
'title': _("Let's encrypt!"),
|
||||
'action_name': _("Encrypt"),
|
||||
'content_message': ugettext("You are going to request certificates for the following domains.<br>"
|
||||
'content_message': gettext("You are going to request certificates for the following domains.<br>"
|
||||
"This operation is safe to run multiple times, "
|
||||
"existing certificates will not be regenerated. "
|
||||
"Also notice that let's encrypt does not currently support wildcard certificates.") + content_error,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||
from django.utils.translation import ngettext, gettext_lazy as _
|
||||
|
||||
from .helpers import is_valid_domain
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.contrib import admin
|
||||
from django.conf.urls import url
|
||||
from django.urls import re_path as url
|
||||
from django.contrib.auth.admin import UserAdmin
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
|
||||
from orchestra.admin.actions import disable, enable
|
||||
|
@ -16,7 +16,7 @@ from .filters import HasCustomAddressListFilter
|
|||
from .models import List
|
||||
|
||||
|
||||
class ListAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||
class ListAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||
list_display = (
|
||||
'name', 'address_name', 'address_domain_link', 'account_link', 'display_active'
|
||||
)
|
||||
|
@ -31,7 +31,7 @@ class ListAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedModel
|
|||
}),
|
||||
(_("Admin"), {
|
||||
'classes': ('wide',),
|
||||
'fields': ('admin_email', 'password1', 'password2'),
|
||||
'fields': ('admin_email',),
|
||||
}),
|
||||
)
|
||||
fieldsets = (
|
||||
|
@ -45,35 +45,15 @@ class ListAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedModel
|
|||
) % settings.LISTS_DEFAULT_DOMAIN,
|
||||
'fields': (('address_name', 'address_domain'),)
|
||||
}),
|
||||
(_("Admin"), {
|
||||
'classes': ('wide',),
|
||||
'fields': ('password',),
|
||||
}),
|
||||
)
|
||||
search_fields = ('name', 'address_name', 'address_domain__name', 'account__username')
|
||||
list_filter = (IsActiveListFilter, HasCustomAddressListFilter)
|
||||
readonly_fields = ('account_link',)
|
||||
change_readonly_fields = ('name',)
|
||||
form = NonStoredUserChangeForm
|
||||
add_form = UserCreationForm
|
||||
list_select_related = ('account', 'address_domain',)
|
||||
filter_by_account_fields = ['address_domain']
|
||||
actions = (disable, enable, list_accounts)
|
||||
|
||||
address_domain_link = admin_link('address_domain', order='address_domain__name')
|
||||
|
||||
def get_urls(self):
|
||||
useradmin = UserAdmin(List, self.admin_site)
|
||||
return [
|
||||
url(r'^(\d+)/password/$',
|
||||
self.admin_site.admin_view(useradmin.user_change_password))
|
||||
] + super(ListAdmin, self).get_urls()
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
""" set password """
|
||||
if not change:
|
||||
obj.set_password(form.cleaned_data["password1"])
|
||||
super(ListAdmin, self).save_model(request, obj, form, change)
|
||||
|
||||
|
||||
admin.site.register(List, ListAdmin)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import textwrap
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.contrib.orchestration import ServiceController, replace
|
||||
from orchestra.contrib.resources import ServiceMonitor
|
||||
|
@ -48,11 +48,11 @@ class MailmanVirtualDomainController(ServiceController):
|
|||
|
||||
def save(self, mail_list):
|
||||
context = self.get_context(mail_list)
|
||||
#self.include_virtual_alias_domain(context)
|
||||
self.include_virtual_alias_domain(context)
|
||||
|
||||
def delete(self, mail_list):
|
||||
context = self.get_context(mail_list)
|
||||
#self.exclude_virtual_alias_domain(context)
|
||||
self.exclude_virtual_alias_domain(context)
|
||||
|
||||
def commit(self):
|
||||
context = self.get_context_files()
|
||||
|
@ -100,29 +100,70 @@ class MailmanController(MailmanVirtualDomainController):
|
|||
aliases = ['# %(banner)s' % context]
|
||||
for suffix in self.address_suffixes:
|
||||
context['suffix'] = suffix
|
||||
# Because mailman doesn't properly handle lists aliases we need two virtual aliases
|
||||
aliases.append("%(address_name)s%(suffix)s@%(domain)s\t%(name)s%(suffix)s@grups.pangea.org" % context)
|
||||
# Because mailman doesn't properly handle lists aliases we need virtual aliases
|
||||
if context['address_name'] != context['name']:
|
||||
# And another with the original list name; Mailman generates links with it
|
||||
aliases.append("%(name)s%(suffix)s@%(domain)s\t%(name)s%(suffix)s" % context)
|
||||
aliases.append("%(address_name)s%(suffix)s@%(domain)s\t%(name)s%(suffix)s@grups.pangea.org" % context)
|
||||
return '\n'.join(aliases)
|
||||
|
||||
|
||||
def save(self, mail_list):
|
||||
context = self.get_context(mail_list)
|
||||
|
||||
# Create list
|
||||
cmd = "/opt/mailman/venv/bin/python /usr/local/admin/orchestra_mailman3/save.py %(name)s %(admin)s %(address_name)s@%(domain)s" % context
|
||||
if not mail_list.active:
|
||||
cmd += ' --inactive'
|
||||
self.append(cmd)
|
||||
|
||||
# Custom domain
|
||||
if mail_list.address:
|
||||
context.update({
|
||||
'aliases': self.get_virtual_aliases(context),
|
||||
'num_entries': 2 if context['address_name'] != context['name'] else 1,
|
||||
})
|
||||
self.append(textwrap.dedent("""\
|
||||
# Create list alias for custom domain
|
||||
aliases='%(aliases)s'
|
||||
if ! grep '\s\s*%(name)s\s*$' %(virtual_alias)s > /dev/null; then
|
||||
echo "${aliases}" >> %(virtual_alias)s
|
||||
UPDATED_VIRTUAL_ALIAS=1
|
||||
else
|
||||
if grep -E '(%(address_name)s|%(name)s)@(%(address_domain)s|grups.pangea.org)' %(virtual_alias)s > /dev/null ; then
|
||||
sed -i -e '/^.*%(name)s\(-admin\|-bounces\|-confirm\|-join\|-leave\|-owner\|-request\|-subscribe\|-unsubscribe\|@\).*$/d' \\
|
||||
-e '/# .*%(name)s$/d' %(virtual_alias)s
|
||||
echo "${aliases}" >> %(virtual_alias)s
|
||||
UPDATED_VIRTUAL_ALIAS=1
|
||||
fi
|
||||
fi """) % context
|
||||
)
|
||||
else:
|
||||
self.append(textwrap.dedent("""\
|
||||
# Cleanup possible ex-custom domain
|
||||
if grep '\s\s*%(name)s\s*$' %(virtual_alias)s > /dev/null; then
|
||||
#sed -i "/^.*\s%(name)s\s*$/d" %(virtual_alias)s
|
||||
sed -i -e '/^.*%(name)s\(-admin\|-bounces\|-confirm\|-join\|-leave\|-owner\|-request\|-subscribe\|-unsubscribe\|@\).*$/d' \\
|
||||
-e '/# .*%(name)s$/d' %(virtual_alias)s
|
||||
fi""") % context
|
||||
)
|
||||
|
||||
|
||||
def delete(self, mail_list):
|
||||
context = self.get_context(mail_list)
|
||||
|
||||
# Custom domain delete
|
||||
self.append(textwrap.dedent("""\
|
||||
# Cleanup possible ex-custom domain
|
||||
if grep '\s\s*%(name)s\s*$' %(virtual_alias)s > /dev/null; then
|
||||
sed -i -e '/^.*%(name)s\(-admin\|-bounces\|-confirm\|-join\|-leave\|-owner\|-request\|-subscribe\|-unsubscribe\|@\).*$/d' \\
|
||||
-e '/# .*%(name)s$/d' %(virtual_alias)s
|
||||
fi""") % context
|
||||
)
|
||||
|
||||
# Delete list
|
||||
cmd = "/opt/mailman/venv/bin/python /usr/local/admin/orchestra_mailman3/delete.py %(name)s %(admin)s %(address_name)s@%(domain)s" % context
|
||||
if not mail_list.active:
|
||||
cmd += ' --inactive'
|
||||
cmd = "/opt/mailman/venv/bin/python /usr/local/admin/orchestra_mailman3/delete.py %(name)s" % context
|
||||
self.append(cmd)
|
||||
|
||||
|
||||
def commit(self):
|
||||
pass
|
||||
|
||||
|
@ -141,7 +182,6 @@ class MailmanController(MailmanVirtualDomainController):
|
|||
context.update({
|
||||
'banner': self.get_banner(mail_list),
|
||||
'name': mail_list.name,
|
||||
'password': mail_list.password,
|
||||
'domain': mail_list.address_domain or settings.LISTS_DEFAULT_DOMAIN,
|
||||
'address_name': mail_list.get_address_name(),
|
||||
'address_domain': mail_list.address_domain,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django.contrib.admin import SimpleListFilter
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class HasCustomAddressListFilter(SimpleListFilter):
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
# Generated by Django 2.2.28 on 2023-09-01 14:59
|
||||
|
||||
from django.db import models, migrations
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import orchestra.core.validators
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('domains', '__first__'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('domains', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='List',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, verbose_name='ID', serialize=False, primary_key=True)),
|
||||
('name', models.CharField(max_length=128, validators=[orchestra.core.validators.validate_name], unique=True, verbose_name='name', help_text='Default list address <name>@lists.orchestra.lan')),
|
||||
('address_name', models.CharField(max_length=128, validators=[orchestra.core.validators.validate_name], verbose_name='address name', blank=True)),
|
||||
('admin_email', models.EmailField(max_length=254, verbose_name='admin email', help_text='Administration email address')),
|
||||
('is_active', models.BooleanField(default=True, verbose_name='active', help_text='Designates whether this account should be treated as active. Unselect this instead of deleting accounts.')),
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(help_text='Default list address <name>@grups.pangea.org', max_length=64, unique=True, validators=[orchestra.core.validators.validate_name], verbose_name='name')),
|
||||
('address_name', models.CharField(blank=True, max_length=64, validators=[orchestra.core.validators.validate_name], verbose_name='address name')),
|
||||
('admin_email', models.EmailField(help_text='Administration email address', max_length=254, verbose_name='admin email')),
|
||||
('is_active', models.BooleanField(default=True, help_text='Designates whether this account should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
|
||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='lists', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
|
||||
('address_domain', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, null=True, blank=True, to='domains.Domain', verbose_name='address domain')),
|
||||
('address_domain', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='domains.Domain', verbose_name='address domain')),
|
||||
],
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='list',
|
||||
unique_together=set([('address_name', 'address_domain')]),
|
||||
options={
|
||||
'unique_together': {('address_name', 'address_domain')},
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,24 +1,13 @@
|
|||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.core.validators import validate_name
|
||||
|
||||
from . import settings
|
||||
|
||||
|
||||
class ListQuerySet(models.QuerySet):
|
||||
def create(self, **kwargs):
|
||||
""" Sets password if provided, all within a single DB operation """
|
||||
password = kwargs.pop('password')
|
||||
instance = self.model(**kwargs)
|
||||
if password:
|
||||
instance.set_password(password)
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
|
||||
# TODO address and domain, perhaps allow only domain?
|
||||
class List(models.Model):
|
||||
name = models.CharField(_("name"), max_length=64, unique=True, validators=[validate_name],
|
||||
|
@ -35,9 +24,6 @@ class List(models.Model):
|
|||
is_active = models.BooleanField(_("active"), default=True,
|
||||
help_text=_("Designates whether this account should be treated as active. "
|
||||
"Unselect this instead of deleting accounts."))
|
||||
password = None
|
||||
|
||||
objects = ListQuerySet.as_manager()
|
||||
|
||||
class Meta:
|
||||
unique_together = ('address_name', 'address_domain')
|
||||
|
@ -75,9 +61,6 @@ class List(models.Model):
|
|||
def get_username(self):
|
||||
return self.name
|
||||
|
||||
def set_password(self, password):
|
||||
self.password = password
|
||||
|
||||
def get_absolute_url(self):
|
||||
context = {
|
||||
'name': self.name
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.core.validators import RegexValidator
|
||||
from django.forms import widgets
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from orchestra.api.serializers import SetPasswordHyperlinkedSerializer, RelatedHyperlinkedModelSerializer
|
||||
|
|
|
@ -9,32 +9,33 @@ LISTS_DOMAIN_MODEL = Setting('LISTS_DOMAIN_MODEL',
|
|||
|
||||
|
||||
LISTS_DEFAULT_DOMAIN = Setting('LISTS_DEFAULT_DOMAIN',
|
||||
'lists.{}'.format(ORCHESTRA_BASE_DOMAIN),
|
||||
'grups.{}'.format(ORCHESTRA_BASE_DOMAIN),
|
||||
help_text="Uses <tt>ORCHESTRA_BASE_DOMAIN</tt> by default."
|
||||
)
|
||||
|
||||
|
||||
LISTS_LIST_URL = Setting('LISTS_LIST_URL',
|
||||
'https://lists.{}/mailman/listinfo/%(name)s'.format(ORCHESTRA_BASE_DOMAIN),
|
||||
# 'https://lists.{}/mailman/listinfo/%(name)s'.format(ORCHESTRA_BASE_DOMAIN),
|
||||
'https://www.{0}/mailman3/lists/%(name)s.{0}'.format(LISTS_DEFAULT_DOMAIN),
|
||||
help_text="Uses <tt>ORCHESTRA_BASE_DOMAIN</tt> by default."
|
||||
)
|
||||
|
||||
|
||||
LISTS_MAILMAN_POST_LOG_PATH = Setting('LISTS_MAILMAN_POST_LOG_PATH',
|
||||
'/var/log/mailman/post'
|
||||
'/var/log/mailman3/smtp'
|
||||
)
|
||||
|
||||
|
||||
LISTS_MAILMAN_ROOT_DIR = Setting('LISTS_MAILMAN_ROOT_DIR',
|
||||
'/var/lib/mailman'
|
||||
'/var/lib/mailman3'
|
||||
)
|
||||
|
||||
|
||||
LISTS_VIRTUAL_ALIAS_PATH = Setting('LISTS_VIRTUAL_ALIAS_PATH',
|
||||
'/etc/postfix/mailman_virtual_aliases'
|
||||
'/etc/postfix/mailman3_virtusertable'
|
||||
)
|
||||
|
||||
|
||||
LISTS_VIRTUAL_ALIAS_DOMAINS_PATH = Setting('LISTS_VIRTUAL_ALIAS_DOMAINS_PATH',
|
||||
'/etc/postfix/mailman_virtual_domains'
|
||||
'/etc/postfix/mailman3_virtdomains'
|
||||
)
|
||||
|
|
|
@ -8,7 +8,7 @@ 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 _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
|
||||
from orchestra.admin.actions import disable, enable
|
||||
|
@ -20,7 +20,7 @@ from orchestra.core import caches
|
|||
|
||||
from . import settings
|
||||
from .actions import SendMailboxEmail, SendAddressEmail
|
||||
from .filters import HasMailboxListFilter, HasForwardListFilter, HasAddressListFilter
|
||||
from .filters import HasMailboxListFilter, HasForwardListFilter, HasAddressListFilter, HasTipeServerFilter
|
||||
from .forms import MailboxCreationForm, MailboxChangeForm, AddressForm
|
||||
from .models import Mailbox, Address, Autoresponse
|
||||
from .widgets import OpenCustomFilteringOnSelect
|
||||
|
@ -40,7 +40,7 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo
|
|||
list_display = (
|
||||
'name', 'account_link', 'display_filtering', 'display_addresses', 'display_active',
|
||||
)
|
||||
list_filter = (IsActiveListFilter, HasAddressListFilter, 'filtering')
|
||||
list_filter = (IsActiveListFilter, HasAddressListFilter, 'filtering', HasTipeServerFilter)
|
||||
search_fields = (
|
||||
'account__username', 'account__short_name', 'account__full_name', 'name',
|
||||
'addresses__name', 'addresses__domain__name',
|
||||
|
|
|
@ -4,7 +4,7 @@ import re
|
|||
import textwrap
|
||||
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.contrib.orchestration import ServiceController
|
||||
from orchestra.contrib.resources import ServiceMonitor
|
||||
|
@ -437,14 +437,19 @@ class DovecotMaildirDisk(ServiceMonitor):
|
|||
def prepare(self):
|
||||
super().prepare()
|
||||
current_date = self.current_date.strftime("%Y-%m-%d %H:%M:%S %Z")
|
||||
# self.append(textwrap.dedent("""\
|
||||
# function monitor () {
|
||||
# awk 'BEGIN { size = 0 } NR > 1 { size += $1 } END { print size }' $1 || echo 0
|
||||
# }"""))
|
||||
self.append(textwrap.dedent("""\
|
||||
function monitor () {
|
||||
awk 'BEGIN { size = 0 } NR > 1 { size += $1 } END { print size }' $1 || echo 0
|
||||
SIZE=$(du -sb $1/Maildir/ 2> /dev/null || echo 0) && echo $SIZE | awk '{print $1}'
|
||||
}"""))
|
||||
|
||||
def monitor(self, mailbox):
|
||||
context = self.get_context(mailbox)
|
||||
self.append("echo %(object_id)s $(monitor %(maildir_path)s)" % context)
|
||||
# self.append("echo %(object_id)s $(monitor %(maildir_path)s)" % context)
|
||||
self.append("echo %(object_id)s $(monitor %(home)s)" % context)
|
||||
|
||||
def get_context(self, mailbox):
|
||||
context = {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
from django.contrib.admin import SimpleListFilter
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from orchestra.contrib.orchestration.models import Server
|
||||
from orchestra.contrib.websites.models import Website
|
||||
from orchestra.settings import WEB_SERVERS
|
||||
|
||||
class HasMailboxListFilter(SimpleListFilter):
|
||||
""" Filter addresses whether they have any mailbox or not """
|
||||
|
@ -45,3 +47,17 @@ class HasAddressListFilter(HasMailboxListFilter):
|
|||
elif self.value() == 'False':
|
||||
return queryset.filter(addresses__isnull=True)
|
||||
return queryset
|
||||
|
||||
|
||||
class HasTipeServerFilter(SimpleListFilter):
|
||||
title = _("has type server")
|
||||
parameter_name = 'has_servers'
|
||||
|
||||
def lookups(self, request, model_admin):
|
||||
return [ (x.id, x.name) for x in Server.objects.filter(name__in=WEB_SERVERS) ]
|
||||
|
||||
def queryset(self, request, queryset):
|
||||
if self.value() is not None:
|
||||
serverWebsites = Website.objects.filter(target_server=self.value())
|
||||
return queryset.filter(account__in=[ x.account.id for x in serverWebsites ] )
|
||||
return queryset
|
|
@ -2,7 +2,7 @@ from django import forms
|
|||
from django.contrib.admin import widgets
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.forms import UserCreationForm, UserChangeForm
|
||||
from orchestra.utils.python import AttrDict
|
||||
|
|
|
@ -6,7 +6,7 @@ from django.contrib.auth.hashers import make_password
|
|||
from django.core.validators import RegexValidator, ValidationError
|
||||
from django.db import models
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from . import validators, settings
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import textwrap
|
|||
|
||||
from django.utils.functional import lazy
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.contrib.settings import Setting
|
||||
from orchestra.core.validators import validate_name
|
||||
|
|
|
@ -3,7 +3,7 @@ import os
|
|||
import re
|
||||
|
||||
from django.core.validators import ValidationError, EmailValidator
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.utils import paths
|
||||
from orchestra.utils.sys import run
|
||||
|
|
|
@ -8,7 +8,7 @@ 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 django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.admin import ExtendedModelAdmin
|
||||
from orchestra.admin.utils import admin_link, admin_colored, admin_date, wrap_admin_view
|
||||
|
@ -115,7 +115,7 @@ class MessageAdmin(ExtendedModelAdmin):
|
|||
display_to.short_description = _("To")
|
||||
|
||||
def get_urls(self):
|
||||
from django.conf.urls import url
|
||||
from django.urls import re_path as url
|
||||
urls = super().get_urls()
|
||||
info = self.model._meta.app_label, self.model._meta.model_name
|
||||
urls.insert(0,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
import smtplib
|
||||
from datetime import timedelta
|
||||
from socket import error as SocketError
|
||||
|
@ -5,7 +6,6 @@ from socket import error as SocketError
|
|||
from django.core.mail import get_connection
|
||||
from django.db.models import Q
|
||||
from django.utils import timezone
|
||||
from django.utils.encoding import smart_str
|
||||
|
||||
from orchestra.utils.sys import LockFile, OperationLocked
|
||||
|
||||
|
@ -31,7 +31,7 @@ def send_message(message, connection=None, bulk=settings.MAILER_BULK_MESSAGES):
|
|||
return
|
||||
error = None
|
||||
try:
|
||||
connection.connection.sendmail(message.from_address, [message.to_address], smart_str(message.content))
|
||||
connection.connection.sendmail(message.from_address, [message.to_address], message.content.encode())
|
||||
except (SocketError,
|
||||
smtplib.SMTPSenderRefused,
|
||||
smtplib.SMTPRecipientsRefused,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from . import settings
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.contrib.settings import Setting
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{% extends "admin/change_list.html" %}
|
||||
{% load i18n admin_urls admin_static admin_list %}
|
||||
{% load i18n admin_urls static admin_list %}
|
||||
|
||||
|
||||
{% block object-tools-items %}
|
||||
|
|
|
@ -4,7 +4,7 @@ from django.urls import reverse
|
|||
from django.db import models
|
||||
from django.utils.html import format_html
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.admin import ExtendedModelAdmin
|
||||
from orchestra.admin.actions import disable, enable
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.db import models
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.core.validators import validate_name
|
||||
from orchestra.models.fields import NullableCharField
|
||||
|
|
|
@ -4,7 +4,7 @@ from django.contrib import messages
|
|||
from django.contrib.admin import helpers
|
||||
from django.shortcuts import render
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||
from django.utils.translation import ngettext, gettext_lazy as _
|
||||
|
||||
from orchestra.admin.utils import get_object_from_url, change_url
|
||||
from orchestra.contrib.orchestration.helpers import message_user
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.contrib import admin, messages
|
||||
from django.utils.html import escape
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.admin import ExtendedModelAdmin, ChangeViewActionsMixin
|
||||
from orchestra.admin.utils import admin_link, admin_date, admin_colored, display_mono, display_code
|
||||
|
|
|
@ -4,7 +4,7 @@ from functools import partial
|
|||
|
||||
from django.apps import apps
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra import plugins
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ from django.core.mail import mail_admins
|
|||
from django.urls import reverse, NoReverseMatch
|
||||
from django.utils.html import escape
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||
from django.utils.translation import ngettext, gettext_lazy as _
|
||||
|
||||
from orchestra import settings as orchestra_settings
|
||||
from orchestra.admin.utils import change_url
|
||||
|
@ -125,7 +125,7 @@ def get_messages(logs):
|
|||
async_url = get_backend_url(async_ids)
|
||||
async_msg = ''
|
||||
if run_async:
|
||||
async_msg = ungettext(
|
||||
async_msg = ngettext(
|
||||
_('<a href="{async_url}">{name}</a> is running on the background'),
|
||||
_('<a href="{async_url}">{run_async} backends</a> are running on the background'),
|
||||
run_async)
|
||||
|
@ -133,7 +133,7 @@ def get_messages(logs):
|
|||
if total == 1:
|
||||
msg = _('<a href="{url}">{name}</a> has fail to execute')
|
||||
else:
|
||||
msg = ungettext(
|
||||
msg = ngettext(
|
||||
_('<a href="{url}">{errors} out of {total} backends</a> has fail to execute'),
|
||||
_('<a href="{url}">{errors} out of {total} backends</a> have fail to execute'),
|
||||
errors)
|
||||
|
@ -147,13 +147,13 @@ def get_messages(logs):
|
|||
if total == 1:
|
||||
msg = _('<a href="{url}">{name}</a> has been executed')
|
||||
else:
|
||||
msg = ungettext(
|
||||
msg = ngettext(
|
||||
_('<a href="{url}">{successes} out of {total} backends</a> has been executed'),
|
||||
_('<a href="{url}">{successes} out of {total} backends</a> have been executed'),
|
||||
successes)
|
||||
msg += ', ' + str(async_msg)
|
||||
else:
|
||||
msg = ungettext(
|
||||
msg = ngettext(
|
||||
_('<a href="{url}">{name}</a> has been executed'),
|
||||
_('<a href="{url}">{total} backends</a> have been executed'),
|
||||
total)
|
||||
|
|
|
@ -5,10 +5,10 @@ from django.contrib.contenttypes.fields import GenericForeignKey
|
|||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.module_loading import autodiscover_modules
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.core.validators import validate_ip_address, validate_hostname, OrValidator
|
||||
from orchestra.models.fields import NullableCharField, MultiSelectField
|
||||
|
@ -128,7 +128,7 @@ class BackendOperationQuerySet(models.QuerySet):
|
|||
def create(self, **kwargs):
|
||||
instance = kwargs.get('instance')
|
||||
if instance and 'instance_repr' not in kwargs:
|
||||
kwargs['instance_repr'] = force_text(instance)[:256]
|
||||
kwargs['instance_repr'] = force_str(instance)[:256]
|
||||
return super(BackendOperationQuerySet, self).create(**kwargs)
|
||||
|
||||
|
||||
|
@ -207,7 +207,7 @@ class Route(models.Model):
|
|||
run_async = models.BooleanField(default=False,
|
||||
help_text=_("Whether or not block the request/response cycle waitting this backend to "
|
||||
"finish its execution. Usually you want slave servers to run asynchronously."))
|
||||
async_actions = MultiSelectField(max_length=256, blank=True,
|
||||
async_actions = MultiSelectField(max_length=256, blank=True, choices=[],
|
||||
help_text=_("Specify individual actions to be executed asynchronoulsy."))
|
||||
# method = models.CharField(_("method"), max_lenght=32, choices=method_choices,
|
||||
# default=MethodBackend.get_default())
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from os import path
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.contrib.settings import Setting
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import django.dispatch
|
||||
|
||||
pre_action = django.dispatch.Signal()
|
||||
|
||||
pre_action = django.dispatch.Signal(providing_args=['backend', 'instance', 'action'])
|
||||
post_action = django.dispatch.Signal()
|
||||
|
||||
post_action = django.dispatch.Signal(providing_args=['backend', 'instance', 'action'])
|
||||
pre_prepare = django.dispatch.Signal()
|
||||
|
||||
pre_prepare = django.dispatch.Signal(providing_args=['backend'])
|
||||
post_prepare = django.dispatch.Signal()
|
||||
|
||||
post_prepare = django.dispatch.Signal(providing_args=['backend'])
|
||||
pre_commit = django.dispatch.Signal()
|
||||
|
||||
pre_commit = django.dispatch.Signal(providing_args=['backend'])
|
||||
post_commit = django.dispatch.Signal()
|
||||
|
||||
post_commit = django.dispatch.Signal(providing_args=['backend'])
|
||||
|
|
|
@ -3,7 +3,7 @@ from django.urls import reverse
|
|||
from django.db import transaction
|
||||
from django.utils import timezone
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||
from django.utils.translation import ngettext, gettext_lazy as _
|
||||
from django.shortcuts import render
|
||||
|
||||
from orchestra.admin.utils import change_url
|
||||
|
@ -95,7 +95,7 @@ class BillSelectedOrders(object):
|
|||
url = reverse('admin:bills_bill_changelist')
|
||||
ids = ','.join([str(b.id) for b in bills])
|
||||
url += '?id__in=%s' % ids
|
||||
msg = ungettext(
|
||||
msg = ngettext(
|
||||
'<a href="{url}">One bill</a> has been created.',
|
||||
'<a href="{url}">{num} bills</a> have been created.',
|
||||
num).format(url=url, num=num)
|
||||
|
@ -126,7 +126,7 @@ def mark_as_ignored(modeladmin, request, queryset):
|
|||
order.mark_as_ignored()
|
||||
modeladmin.log_change(request, order, 'Marked as ignored')
|
||||
num = len(queryset)
|
||||
msg = ungettext(
|
||||
msg = ngettext(
|
||||
_("Selected order has been marked as ignored."),
|
||||
_("%i selected orders have been marked as ignored.") % num,
|
||||
num)
|
||||
|
@ -140,7 +140,7 @@ def mark_as_not_ignored(modeladmin, request, queryset):
|
|||
order.mark_as_not_ignored()
|
||||
modeladmin.log_change(request, order, 'Marked as not ignored')
|
||||
num = len(queryset)
|
||||
msg = ungettext(
|
||||
msg = ngettext(
|
||||
_("Selected order has been marked as not ignored."),
|
||||
_("%i selected orders have been marked as not ignored.") % num,
|
||||
num)
|
||||
|
|
|
@ -6,7 +6,7 @@ from django.db.models import Prefetch
|
|||
from django.utils import timezone
|
||||
from django.utils.html import escape, format_html
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.admin import ExtendedModelAdmin
|
||||
from orchestra.admin.utils import admin_link, admin_date, change_url
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.contrib.bills.models import Invoice, Fee, ProForma
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ from django.apps import apps
|
|||
from django.contrib.admin import SimpleListFilter
|
||||
from django.db.models import Q, Prefetch, F
|
||||
from django.utils import timezone
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from . import settings
|
||||
from .models import MetricStorage
|
||||
|
@ -118,7 +118,7 @@ class IgnoreOrderListFilter(SimpleListFilter):
|
|||
""" Enable default selection different than All """
|
||||
for lookup, title in self.lookup_choices:
|
||||
title = title._proxy____args[0]
|
||||
selected = self.value() == force_text(lookup)
|
||||
selected = self.value() == force_str(lookup)
|
||||
if not selected and title == "Not ignored" and self.value() is None:
|
||||
selected = True
|
||||
# end of workaround
|
||||
|
|
|
@ -2,7 +2,7 @@ from django import forms
|
|||
from django.contrib.admin import widgets
|
||||
from django.utils import timezone
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.admin.forms import AdminFormMixin
|
||||
from orchestra.admin.utils import change_url
|
||||
|
|
|
@ -9,7 +9,7 @@ from django.contrib.contenttypes.fields import GenericForeignKey
|
|||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.models import queryset
|
||||
from orchestra.utils.python import import_class
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n l10n staticfiles admin_urls utils orders %}
|
||||
{% load i18n l10n static admin_urls utils orders %}
|
||||
|
||||
{% block extrastyle %}
|
||||
{{ block.super }}
|
||||
|
|
|
@ -7,7 +7,7 @@ from django.db import transaction
|
|||
from django.shortcuts import render, redirect
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.text import capfirst
|
||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||
from django.utils.translation import ngettext, gettext_lazy as _
|
||||
|
||||
from orchestra.admin.decorators import action_with_confirmation
|
||||
from orchestra.admin.utils import change_url
|
||||
|
@ -38,11 +38,11 @@ def process_transactions(modeladmin, request, queryset):
|
|||
opts = modeladmin.model._meta
|
||||
num = len(queryset)
|
||||
context = {
|
||||
'title': ungettext(
|
||||
'title': ngettext(
|
||||
_("One selected transaction has been processed."),
|
||||
_("%s Selected transactions have been processed.") % num,
|
||||
num),
|
||||
'content_message': ungettext(
|
||||
'content_message': ngettext(
|
||||
_("The following transaction process has been generated, "
|
||||
"you may want to save it on your computer now."),
|
||||
_("The following %s transaction processes have been generated, "
|
||||
|
@ -63,7 +63,7 @@ def mark_as_executed(modeladmin, request, queryset):
|
|||
transaction.mark_as_executed()
|
||||
modeladmin.log_change(request, transaction, _("Executed"))
|
||||
num = len(queryset)
|
||||
msg = ungettext(
|
||||
msg = ngettext(
|
||||
_("One selected transaction has been marked as executed."),
|
||||
_("%s selected transactions have been marked as executed.") % num,
|
||||
num)
|
||||
|
@ -79,7 +79,7 @@ def mark_as_secured(modeladmin, request, queryset):
|
|||
transaction.mark_as_secured()
|
||||
modeladmin.log_change(request, transaction, _("Secured"))
|
||||
num = len(queryset)
|
||||
msg = ungettext(
|
||||
msg = ngettext(
|
||||
_("One selected transaction has been marked as secured."),
|
||||
_("%s selected transactions have been marked as secured.") % num,
|
||||
num)
|
||||
|
@ -95,7 +95,7 @@ def mark_as_rejected(modeladmin, request, queryset):
|
|||
transaction.mark_as_rejected()
|
||||
modeladmin.log_change(request, transaction, _("Rejected"))
|
||||
num = len(queryset)
|
||||
msg = ungettext(
|
||||
msg = ngettext(
|
||||
_("One selected transaction has been marked as rejected."),
|
||||
_("%s selected transactions have been marked as rejected.") % num,
|
||||
num)
|
||||
|
@ -134,7 +134,7 @@ def mark_process_as_executed(modeladmin, request, queryset):
|
|||
process.mark_as_executed()
|
||||
modeladmin.log_change(request, process, _("Executed"))
|
||||
num = len(queryset)
|
||||
msg = ungettext(
|
||||
msg = ngettext(
|
||||
_("One selected process has been marked as executed."),
|
||||
_("%s selected processes have been marked as executed.") % num,
|
||||
num)
|
||||
|
@ -150,7 +150,7 @@ def abort(modeladmin, request, queryset):
|
|||
process.abort()
|
||||
modeladmin.log_change(request, process, _("Aborted"))
|
||||
num = len(queryset)
|
||||
msg = ungettext(
|
||||
msg = ngettext(
|
||||
_("One selected process has been aborted."),
|
||||
_("%s selected processes have been aborted.") % num,
|
||||
num)
|
||||
|
@ -166,7 +166,7 @@ def commit(modeladmin, request, queryset):
|
|||
transaction.mark_as_rejected()
|
||||
modeladmin.log_change(request, transaction, _("Rejected"))
|
||||
num = len(queryset)
|
||||
msg = ungettext(
|
||||
msg = ngettext(
|
||||
_("One selected transaction has been marked as rejected."),
|
||||
_("%s selected transactions have been marked as rejected.") % num,
|
||||
num)
|
||||
|
|
|
@ -3,7 +3,7 @@ from django.urls import reverse
|
|||
from django.http import HttpResponseRedirect
|
||||
from django.utils.html import format_html
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.admin import ChangeViewActionsMixin, ExtendedModelAdmin
|
||||
from orchestra.admin.utils import admin_colored, admin_link, admin_date
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django.contrib import messages
|
||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||
from django.utils.translation import ngettext, gettext_lazy as _
|
||||
|
||||
from .models import Transaction
|
||||
|
||||
|
@ -29,7 +29,7 @@ def post_delete_processes(modeladmin, request, related_transactions):
|
|||
transaction.save(update_fields=('state', 'modified_at'))
|
||||
num += 1
|
||||
modeladmin.log_change(request, transaction, _("Unprocessed"))
|
||||
messages.success(request, ungettext(
|
||||
messages.success(request, ngettext(
|
||||
"One related transaction has been marked as <i>waitting for processing</i>",
|
||||
"%i related transactions have been marked as <i>waitting for processing</i>." % num,
|
||||
num
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from orchestra.plugins.forms import PluginDataForm
|
||||
|
|
|
@ -5,7 +5,7 @@ from io import StringIO
|
|||
|
||||
from django import forms
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django_iban.validators import IBANValidator, IBAN_COUNTRY_CODE_LENGTH
|
||||
from rest_framework import serializers
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from jsonfield import JSONField
|
||||
|
||||
from orchestra.models.fields import PrivateFileField
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.contrib.settings import Setting
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue