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