Compare commits

...

25 commits

Author SHA1 Message Date
Jorge Pastor 38d31d42e8 max length 32 databaseuser 2023-11-24 02:23:54 +01:00
Jorge Pastor 7bf7518339 nextcloud size on cron 2023-11-24 02:23:54 +01:00
Jorge Pastor be039bbeeb fix resource agragation otion last value query 2023-11-24 02:23:54 +01:00
Jorge Pastor 465862e444 change update user password on mysql 2023-11-24 02:23:54 +01:00
jorgepastorr 38a671a18a add icon nextcloud on SAS 2023-11-24 02:23:54 +01:00
jorgepastorr bf84b27e8a fix last nyapa with target_server on SAS 2023-11-24 02:23:54 +01:00
jorgepastorr a41243bc70 nyapa hiden target server in SAS 2023-11-24 02:23:54 +01:00
jorgepastorr b2d335879a fix webappUser create user with groups dont exist 2023-11-24 02:23:54 +01:00
jorgepastorr 87ee955531 fix problem with sftpuser onnSAslist and webalizer 2023-11-24 02:23:54 +01:00
jorgepastorr 8ff8676773 delete local bokworm settiongs 2023-11-24 02:23:54 +01:00
jorgepastorr f8e20f448c delete fields password in lists
edited 2023/11/24 by pedro
2023-11-24 02:23:54 +01:00
jorgepastorr 727e63c9af add filter servers on accounts and mailboxes to send messages 2023-11-24 02:23:54 +01:00
jorgepastorr 9f50bcc672 hidden sftpuser in webalizer form 2023-11-24 02:23:54 +01:00
jorgepastorr 8f84b4fee9 hidden user,password in servers without webappusers 2023-11-24 02:23:54 +01:00
jorgepastorr 4475b3257e delete local bookworm 2023-11-24 02:23:54 +01:00
jorgepastorr 708bbb3a3f websites complete fusion 2023-11-24 02:23:54 +01:00
jorgepastorr 4368b40d00 wordpress complete 2023-11-24 02:23:54 +01:00
jorgepastorr dacc046dc0 webapp php complete 2023-11-24 02:23:54 +01:00
jorgepastorr 50b83c31bd webapps static complete 2023-11-24 02:23:54 +01:00
jorgepastorr 24baf1bb70 webapp static form
edited 2023/11/24 by pedro
2023-11-24 02:23:54 +01:00
jorgepastorr 7d9805869d webappusers in new servers
edited 2023/11/24 by pedro
2023-11-24 02:23:54 +01:00
jorgepastorr d6c9620b54 mainusers only in newservers 2023-11-24 02:23:54 +01:00
jorgepastorr 27463807f5 systemusers in new servers 2023-11-24 02:23:54 +01:00
jorgepastorr f63134f3fe main system users in new servers 2023-11-24 02:23:54 +01:00
Jorge Pastor 39eea70b79 inicio 2023/07/09
edited 2023/11/24 by pedro
2023-11-24 02:23:54 +01:00
224 changed files with 1902 additions and 586 deletions

View file

@ -170,10 +170,10 @@ django-admin.py compilemessages -l ca
https://docs.djangoproject.com/en/1.7/topics/i18n/translation/#joining-strings-string-concat
from django.utils.translation import ugettext
from django.utils.translation import gettext
from django.utils import translation
translation.activate('ca')
ugettext("Description")
gettext("Description")
* saas validate_creation generic approach, for all backends. standard output

View file

@ -59,7 +59,7 @@
```python
import os
import textwrap
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.contrib.orchestration import ServiceController, replace
from orchestra.contrib.resources import ServiceMonitor

View file

@ -6,7 +6,7 @@ from django.contrib import admin
from django.urls import reverse
from django.shortcuts import render, redirect
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from .dashboard import *
from .options import *

View file

@ -3,7 +3,7 @@ from functools import partial
from django.contrib import admin
from django.core.mail import send_mass_mail
from django.shortcuts import render
from django.utils.translation import ungettext, ugettext_lazy as _
from django.utils.translation import ngettext, gettext_lazy as _
from .. import settings
@ -81,7 +81,7 @@ class SendEmail(object):
if extra_to:
emails.append((subject, message, email_from, extra_to))
send_mass_mail(emails, fail_silently=False)
msg = ungettext(
msg = ngettext(
_("Message has been sent to one %s.") % self.opts.verbose_name_plural,
_("Message has been sent to %i %s.") % (num, self.opts.verbose_name_plural),
num
@ -124,7 +124,7 @@ def base_disable(modeladmin, request, queryset, disable=True):
'verbose_name_plural': opts.verbose_name_plural,
'num': num
}
msg = ungettext(
msg = ngettext(
_("Selected %(verbose_name)s and related services has been %(action_name)s.") % context,
_("%(num)s selected %(verbose_name_plural)s and related services have been %(action_name)s.") % context,
num)

View file

@ -1,5 +1,5 @@
from django.urls import reverse
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from fluent_dashboard import dashboard, appsettings
from fluent_dashboard.modules import CmsAppIconList

View file

@ -4,11 +4,10 @@ from django.contrib import messages
from django.contrib.admin import helpers
from django.core.exceptions import ValidationError
from django.template.response import TemplateResponse
from django.utils.decorators import available_attrs
from django.utils.encoding import force_text
from django.utils.encoding import force_str
from django.utils.html import format_html
from django.utils.text import capfirst
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
def admin_field(method):
@ -50,7 +49,7 @@ def action_with_confirmation(action_name=None, extra_context=None, validator=Non
"""
def decorator(func, extra_context=extra_context, template=template, action_name=action_name, validatior=validator):
@wraps(func, assigned=available_attrs(func))
@wraps(func)
def inner(modeladmin, request, queryset, action_name=action_name, extra_context=extra_context, validator=validator):
if validator is not None:
try:
@ -69,10 +68,10 @@ def action_with_confirmation(action_name=None, extra_context=None, validator=Non
action_value = func.__name__
if len(queryset) == 1:
objects_name = force_text(opts.verbose_name)
objects_name = force_str(opts.verbose_name)
obj = queryset.get()
else:
objects_name = force_text(opts.verbose_name_plural)
objects_name = force_str(opts.verbose_name_plural)
obj = None
if not action_name:
action_name = func.__name__

View file

@ -5,8 +5,8 @@ from django import forms
from django.contrib.admin import helpers
from django.core import validators
from django.forms.models import modelformset_factory, BaseModelFormSet
from django.template import Template
from django.utils.translation import ugettext_lazy as _
from django.template import Template, Context
from django.utils.translation import gettext_lazy as _
from orchestra.forms.widgets import SpanWidget
@ -31,7 +31,7 @@ class AdminFormMixin(object):
context = {
'adminform': adminform
}
return template.render(context)
return template.render(Context(context))
class AdminFormSet(BaseModelFormSet):
@ -74,7 +74,7 @@ class AdminFormSet(BaseModelFormSet):
context = {
'formset': self
}
return template.render(context)
return template.render(Context(context))
class AdminPasswordChangeForm(forms.Form):

View file

@ -3,7 +3,7 @@ from copy import deepcopy
from admin_tools.menu import items, Menu
from django.urls import reverse
from django.utils.text import capfirst
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.core import services, accounts, administration
@ -73,7 +73,7 @@ class OrchestraMenu(Menu):
self.children = [
# items.MenuItem(
# mark_safe('{site_name} <span style="{version_style}">v{version}</span>'.format(
# site_name=force_text(settings.SITE_VERBOSE_NAME),
# site_name=force_str(settings.SITE_VERBOSE_NAME),
# version_style="text-transform:none; float:none; font-size:smaller; background:none;",
# version=get_version())),
# reverse('admin:index')

View file

@ -1,7 +1,7 @@
from urllib import parse
from django import forms
from django.conf.urls import url
from django.urls import re_path as url
from django.contrib import admin, messages
from django.contrib.admin.options import IS_POPUP_VAR
from django.contrib.admin.utils import unquote
@ -12,9 +12,9 @@ from django.forms.models import BaseInlineFormSet
from django.shortcuts import get_object_or_404
from django.template.response import TemplateResponse
from django.utils.decorators import method_decorator
from django.utils.encoding import force_text
from django.utils.encoding import force_str
from django.utils.html import escape
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from django.views.decorators.debug import sensitive_post_parameters
from orchestra.models.utils import has_db_field
@ -230,7 +230,7 @@ class ExtendedModelAdmin(ChangeViewActionsMixin,
if obj is None:
opts = self.model._meta
raise Http404(_('%(name)s object with primary key %(key)r does not exist.') % {
'name': force_text(opts.verbose_name), 'key': escape(object_id)})
'name': force_str(opts.verbose_name), 'key': escape(object_id)})
return obj

View file

@ -1,8 +1,8 @@
from django.contrib.admin.options import get_content_type_for_model
from django.conf import settings as django_settings
from django.utils.encoding import force_text
from django.utils.encoding import force_str
from django.utils.module_loading import autodiscover_modules
from django.utils.translation import ugettext as _
from django.utils.translation import gettext as _
from rest_framework.routers import DefaultRouter
from orchestra import settings
@ -52,7 +52,7 @@ class LogApiMixin(object):
user_id=request.user.pk,
content_type_id=get_content_type_for_model(instance).pk,
object_id=instance.pk,
object_repr=force_text(instance),
object_repr=force_str(instance),
action_flag=action,
change_message=message,
)

View file

@ -3,7 +3,7 @@ import copy
from django.core.exceptions import ValidationError
from django.db import models
from django.forms import widgets
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from rest_framework.utils import model_meta

View file

@ -9,10 +9,10 @@ from django.db import router
from django.shortcuts import redirect, render
from django.template.response import TemplateResponse
from django.utils import timezone
from django.utils.encoding import force_text
from django.utils.encoding import force_str
from django.utils.html import format_html
from django.utils.text import capfirst
from django.utils.translation import ungettext, ugettext_lazy as _
from django.utils.translation import ngettext, gettext_lazy as _
from orchestra.core import services
@ -84,7 +84,7 @@ def delete_related_services(modeladmin, request, queryset):
def format(obj, account=False):
has_admin = obj.__class__ in admin_site._registry
opts = obj._meta
no_edit_link = '%s: %s' % (capfirst(opts.verbose_name), force_text(obj))
no_edit_link = '%s: %s' % (capfirst(opts.verbose_name), force_str(obj))
if has_admin:
try:
@ -154,7 +154,7 @@ def delete_related_services(modeladmin, request, queryset):
if accounts:
relateds = len(to_delete)
for obj in to_delete:
obj_display = force_text(obj)
obj_display = force_str(obj)
modeladmin.log_deletion(request, obj, obj_display)
obj.delete()
context = {
@ -167,9 +167,9 @@ def delete_related_services(modeladmin, request, queryset):
return None
if len(queryset) == 1:
objects_name = force_text(opts.verbose_name)
objects_name = force_str(opts.verbose_name)
else:
objects_name = force_text(opts.verbose_name_plural)
objects_name = force_str(opts.verbose_name_plural)
model_count = {}
for model, objs in collector.model_objs.items():
@ -214,7 +214,7 @@ def disable_selected(modeladmin, request, queryset, disable=True):
account.disable() if disable else account.enable()
modeladmin.log_change(request, account, verbose_action_name.capitalize())
n += 1
modeladmin.message_user(request, ungettext(
modeladmin.message_user(request, ngettext(
_("One account has been successfully %s.") % verbose_action_name,
_("%i accounts have been successfully %s.") % (n, verbose_action_name),
n)
@ -227,7 +227,7 @@ def disable_selected(modeladmin, request, queryset, disable=True):
def format(obj):
has_admin = obj.__class__ in admin_site._registry
opts = obj._meta
no_edit_link = '%s: %s' % (capfirst(opts.verbose_name), force_text(obj))
no_edit_link = '%s: %s' % (capfirst(opts.verbose_name), force_str(obj))
if has_admin:
try:
admin_url = reverse(
@ -258,9 +258,9 @@ def disable_selected(modeladmin, request, queryset, disable=True):
display.append([format(account), current])
if len(queryset) == 1:
objects_name = force_text(opts.verbose_name)
objects_name = force_str(opts.verbose_name)
else:
objects_name = force_text(opts.verbose_name_plural)
objects_name = force_str(opts.verbose_name_plural)
context = dict(
admin_site.each_context(request),

View file

@ -4,7 +4,7 @@ from urllib.parse import parse_qsl
from django import forms
from django.apps import apps
from django.conf.urls import url
from django.urls import re_path as url
from django.contrib import admin, messages
from django.contrib.admin.utils import unquote
from django.contrib.auth import admin as auth
@ -12,7 +12,7 @@ from django.urls import reverse
from django.http import HttpResponseRedirect
from django.templatetags.static import static
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
from orchestra.admin.actions import SendEmail
@ -26,12 +26,13 @@ from .actions import (list_contacts, service_report, delete_related_services, di
enable_selected)
from .forms import AccountCreationForm
from .models import Account
from .filters import HasTipeServerFilter
class AccountAdmin(ChangePasswordAdminMixin, auth.UserAdmin, ExtendedModelAdmin):
list_display = ('username', 'full_name', 'type', 'is_active')
list_filter = (
'type', 'is_active',
'type', 'is_active', HasTipeServerFilter
)
add_fieldsets = (
(_("User"), {

View file

@ -1,4 +1,4 @@
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from rest_framework import viewsets, exceptions
from orchestra.api import router, SetPasswordApiMixin, LogApiMixin

View file

@ -1,6 +1,6 @@
from django.apps import AppConfig
from django.db.models.signals import post_migrate
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.core import services, accounts

View file

@ -1,7 +1,9 @@
from django.contrib.admin import SimpleListFilter
from django.db.models import Q
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.contrib.orchestration.models import Server
from orchestra.contrib.websites.models import Website
from orchestra.settings import WEB_SERVERS
class IsActiveListFilter(SimpleListFilter):
title = _("is active")
@ -25,3 +27,16 @@ class IsActiveListFilter(SimpleListFilter):
elif self.value() == 'object':
return queryset.filter(is_active=False)
return queryset
class HasTipeServerFilter(SimpleListFilter):
title = _("has type server")
parameter_name = 'has_servers'
def lookups(self, request, model_admin):
return [ (x.id, x.name) for x in Server.objects.filter(name__in=WEB_SERVERS) ]
def queryset(self, request, queryset):
if self.value() is not None:
serverWebsites = Website.objects.filter(target_server=self.value())
return queryset.filter(id__in=[ x.account.id for x in serverWebsites ] )
return queryset

View file

@ -4,7 +4,7 @@ from collections import OrderedDict
from django import forms
from django.core.exceptions import ValidationError
from django.apps import apps
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.forms import UserCreationForm

View file

@ -5,7 +5,7 @@ from django.db import models
from django.db.models import signals
from django.apps import apps
from django.utils import timezone, translation
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
#from orchestra.contrib.orchestration.middlewares import OperationsMiddleware
#from orchestra.contrib.orchestration import Operation
@ -165,7 +165,6 @@ class Account(auth.AbstractBaseUser):
elif obj and getattr(obj, 'account', None) == self:
return True
def has_perms(self, perm_list, obj=None):
"""
Returns True if the user has each of the specified permissions. If

View file

@ -1,4 +1,4 @@
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.contrib.settings import Setting
from orchestra.settings import ORCHESTRA_BASE_DOMAIN

View file

@ -1,5 +1,5 @@
{% extends "orchestra/admin/change_form.html" %}
{% load i18n admin_urls admin_static admin_modify %}
{% load i18n admin_urls static admin_modify %}
{% block breadcrumbs %}

View file

@ -12,7 +12,7 @@ from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, redirect
from django.utils import translation, timezone
from django.utils.safestring import mark_safe
from django.utils.translation import ungettext, ugettext_lazy as _
from django.utils.translation import ngettext, gettext_lazy as _
from orchestra.admin.decorators import action_with_confirmation
from orchestra.admin.forms import AdminFormSet
@ -69,7 +69,7 @@ def close_bills(modeladmin, request, queryset, action='close_bills'):
'url': url,
'num': num,
}
message = ungettext(
message = ngettext(
_('<a href="%(url)s">One related transaction</a> has been created') % context,
_('<a href="%(url)s">%(num)i related transactions</a> have been created') % context,
num)
@ -111,7 +111,7 @@ def send_bills_action(modeladmin, request, queryset):
bill.send()
modeladmin.log_change(request, bill, 'Sent')
num += 1
messages.success(request, ungettext(
messages.success(request, ngettext(
_("One bill has been sent."),
_("%i bills have been sent.") % num,
num))
@ -135,7 +135,7 @@ def download_bills(modeladmin, request, queryset):
pdf = bill.as_pdf()
archive.writestr('%s.pdf' % bill.number, pdf)
archive.close()
response = HttpResponse(bytesio.getvalue(), content_type='application/pdf')
response = HttpResponse(bytesio.getvalue(), content_type='application/zip')
response['Content-Disposition'] = 'attachment; filename="orchestra-bills.zip"'
return response
bill = queryset[0]
@ -299,7 +299,7 @@ def amend_bills(modeladmin, request, queryset):
'url': amend_url,
'num': num,
}
messages.success(request, mark_safe(ungettext(
messages.success(request, mark_safe(ngettext(
_('<a href="%(url)s">One amendment bill</a> have been generated.') % context,
_('<a href="%(url)s">%(num)i amendment bills</a> have been generated.') % context,
num

View file

@ -1,5 +1,5 @@
from django import forms
from django.conf.urls import url
from django.urls import re_path as url
from django.contrib import admin, messages
from django.contrib.admin.utils import unquote
from django.urls import reverse
@ -9,7 +9,7 @@ from django.db.models.functions import Coalesce
from django.templatetags.static import static
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from django.shortcuts import redirect
from orchestra.admin import ExtendedModelAdmin
@ -126,7 +126,7 @@ class ClosedBillLineInline(BillLineInline):
return line.compute_total()
display_total.short_description = _("Total")
def has_add_permission(self, request):
def has_add_permission(self, request, obj):
return False

View file

@ -2,7 +2,7 @@ from django.contrib.admin import SimpleListFilter
from django.urls import reverse
from django.db.models import Q
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from . models import Bill

View file

@ -1,5 +1,5 @@
from django import forms
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.admin.utils import admin_link
from orchestra.forms import SpanWidget

View file

@ -1,10 +1,10 @@
from django.contrib import messages
from django.urls import reverse
from django.utils.encoding import force_text
from django.utils.encoding import force_str
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils.text import capfirst
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.admin.utils import change_url
@ -16,14 +16,14 @@ def validate_contact(request, bill, error=True):
valid = True
send = messages.error if error else messages.warning
if not hasattr(bill.account, 'billcontact'):
account = force_text(bill.account)
account = force_str(bill.account)
url = reverse('admin:accounts_account_change', args=(bill.account_id,))
message = msg.format(relation=_("Related"), account=account, url=url)
send(request, mark_safe(message))
valid = False
main = type(bill).account.field.related_model.objects.get_main()
if not hasattr(main, 'billcontact'):
account = force_text(main)
account = force_str(main)
url = reverse('admin:accounts_account_change', args=(main.id,))
message = msg.format(relation=_("Main"), account=account, url=url)
send(request, mark_safe(message))

View file

@ -8,9 +8,9 @@ from django.db.models import F, Sum
from django.db.models.functions import Coalesce
from django.template import loader
from django.utils import timezone, translation
from django.utils.encoding import force_text
from django.utils.encoding import force_str
from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.admin.utils import change_url
from orchestra.contrib.accounts.models import Account
@ -209,7 +209,7 @@ class Bill(models.Model):
def get_payment_state_display(self):
value = self.payment_state
return force_text(dict(self.PAYMENT_STATES).get(value, value))
return force_str(dict(self.PAYMENT_STATES).get(value, value))
def get_current_transaction(self):
return self.transactions.exclude_rejected().first()

View file

@ -1,6 +1,6 @@
from django import forms
from django.contrib import admin
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.admin import AtLeastOneRequiredInlineFormSet, ExtendedModelAdmin
from orchestra.admin.actions import SendEmail

View file

@ -1,5 +1,5 @@
from django.contrib.admin import SimpleListFilter
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from .models import Contact

View file

@ -1,7 +1,7 @@
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.core import validators
from orchestra.models.fields import MultiSelectField

View file

@ -1,9 +1,9 @@
from django.conf.urls import url
from django.urls import re_path as url
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
from orchestra.admin.utils import change_url
@ -11,7 +11,7 @@ from orchestra.contrib.accounts.actions import list_accounts
from orchestra.contrib.accounts.admin import SelectAccountAdminMixin
from .filters import HasUserListFilter, HasDatabaseListFilter
from .forms import DatabaseCreationForm, DatabaseUserChangeForm, DatabaseUserCreationForm
from .forms import DatabaseCreationForm, DatabaseUserChangeForm, DatabaseUserCreationForm, DatabaseForm
from .models import Database, DatabaseUser
def save_selected(modeladmin, request, queryset):
@ -20,21 +20,21 @@ def save_selected(modeladmin, request, queryset):
save_selected.short_description = "Re-save selected objects"
class DatabaseAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
list_display = ('name', 'type', 'display_users', 'account_link')
list_display = ('name', 'type', 'target_server', 'display_users', 'account_link')
list_filter = ('type', HasUserListFilter)
search_fields = ('name', 'account__username')
change_readonly_fields = ('name', 'type')
change_readonly_fields = ('name', 'type', 'target_server')
extra = 1
fieldsets = (
(None, {
'classes': ('extrapretty',),
'fields': ('account_link', 'name', 'type', 'users', 'display_users', 'comments'),
'fields': ('account_link', 'name', 'type', 'users', 'display_users', 'comments', 'target_server'),
}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('account_link', 'name', 'type')
'fields': ('account_link', 'name', 'type', 'target_server')
}),
(_("Create new user"), {
'classes': ('wide',),
@ -45,11 +45,10 @@ class DatabaseAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
'fields': ('user',)
}),
)
form = DatabaseForm
add_form = DatabaseCreationForm
readonly_fields = ('account_link', 'display_users',)
filter_horizontal = ['users']
filter_by_account_fields = ('users',)
list_prefetch_related = ('users',)
actions = (list_accounts, save_selected)
@mark_safe
@ -71,6 +70,7 @@ class DatabaseAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
username=form.cleaned_data['username'],
type=obj.type,
account_id=obj.account.pk,
target_server=form.cleaned_data['target_server'],
)
user.set_password(form.cleaned_data["password1"])
user.save()
@ -78,22 +78,22 @@ class DatabaseAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
class DatabaseUserAdmin(SelectAccountAdminMixin, ChangePasswordAdminMixin, ExtendedModelAdmin):
list_display = ('username', 'type', 'display_databases', 'account_link')
list_display = ('username', 'target_server', 'type', 'display_databases', 'account_link')
list_filter = ('type', HasDatabaseListFilter)
search_fields = ('username', 'account__username')
form = DatabaseUserChangeForm
add_form = DatabaseUserCreationForm
change_readonly_fields = ('username', 'type')
change_readonly_fields = ('username', 'type', 'target_server')
fieldsets = (
(None, {
'classes': ('extrapretty',),
'fields': ('account_link', 'username', 'password', 'type', 'display_databases')
'fields': ('account_link', 'username', 'password', 'type', 'display_databases', 'target_server', 'permision')
}),
)
add_fieldsets = (
(None, {
'classes': ('extrapretty',),
'fields': ('account_link', 'username', 'password1', 'password2', 'type')
'fields': ('account_link', 'username', 'password1', 'password2', 'type', 'target_server', 'permision')
}),
)
readonly_fields = ('account_link', 'display_databases',)

View file

@ -1,5 +1,5 @@
from django.apps import AppConfig
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.core import services

View file

@ -1,6 +1,6 @@
import textwrap
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.contrib.orchestration import ServiceController, replace
from orchestra.contrib.resources import ServiceMonitor
@ -36,10 +36,16 @@ class MySQLController(ServiceController):
'username': user.username,
'grant': 'WITH GRANT OPTION' if user == context['owner'] else ''
})
self.append(textwrap.dedent("""\
mysql -e 'GRANT ALL PRIVILEGES ON `%(database)s`.* TO "%(username)s"@"%(host)s" %(grant)s;'\
""") % context
)
if user.permision == "ro":
self.append(textwrap.dedent("""\
mysql -e 'GRANT SELECT ON `%(database)s`.* TO "%(username)s"@"%(host)s" %(grant)s;'\
""") % context
)
else:
self.append(textwrap.dedent("""\
mysql -e 'GRANT ALL PRIVILEGES ON `%(database)s`.* TO "%(username)s"@"%(host)s" %(grant)s;'\
""") % context
)
def delete(self, database):
if database.type != database.MYSQL:
@ -85,8 +91,8 @@ class MySQLUserController(ServiceController):
context = self.get_context(user)
self.append(textwrap.dedent("""\
# Create user %(username)s
mysql -e 'CREATE USER "%(username)s"@"%(host)s";' || true # User already exists
mysql -e 'UPDATE mysql.user SET Password="%(password)s" WHERE User="%(username)s";'\
mysql -e 'CREATE USER IF NOT EXISTS "%(username)s"@"%(host)s";'
mysql -e 'ALTER USER IF EXISTS "%(username)s"@"%(host)s" IDENTIFIED BY PASSWORD "%(password)s";'\
""") % context
)
@ -172,7 +178,7 @@ class MysqlDisk(ServiceMonitor):
def get_context(self, db):
context = {
'db_name': db.name,
'db_dirname': db.name.replace('-', '@003f'),
'db_dirname': db.name.replace('-', '@002d'),
'db_id': db.pk,
'db_type': db.type,
}

View file

@ -1,5 +1,5 @@
from django.contrib.admin import SimpleListFilter
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
class HasUserListFilter(SimpleListFilter):

View file

@ -3,7 +3,7 @@ from django.contrib.auth.forms import ReadOnlyPasswordHashField
from django.core.exceptions import ValidationError
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.core import validators
@ -31,13 +31,39 @@ class DatabaseUserCreationForm(forms.ModelForm):
return password2
class DatabaseForm(forms.ModelForm):
class Meta:
model = Database
fields = ('name', 'users', 'type', 'account', 'target_server')
def __init__(self, *args, **kwargs):
super(DatabaseForm, self).__init__(*args, **kwargs)
# muestra solo los usuarios del mismo server
account_id = self.instance.account_id
database_server_id = self.instance.target_server_id
if account_id:
self.fields['users'].queryset = DatabaseUser.objects.filter(account=account_id, target_server=database_server_id)
def clean(self):
# verifica que los usuarios petenecen al servidor de la bbdd
database_server_id = self.instance.target_server_id
users = self.cleaned_data.get('users')
if users and database_server_id:
for user in users:
if user.target_server_id != database_server_id:
self.add_error("users", _(f"{user.username} does not belong to the database server"))
return self.cleaned_data
class DatabaseCreationForm(DatabaseUserCreationForm):
username = forms.CharField(label=_("Username"), max_length=16,
username = forms.CharField(label=_("Username"), max_length=32,
required=False, validators=[validators.validate_name],
help_text=_("Required. 16 characters or fewer. Letters, digits and "
help_text=_("Required. 32 characters or fewer. Letters, digits and "
"@/./+/-/_ only."),
error_messages={
'invalid': _("This value may contain 16 characters or fewer, only letters, numbers and "
'invalid': _("This value may contain 32 characters or fewer, only letters, numbers and "
"@/./+/-/_ characters.")})
user = forms.ModelChoiceField(required=False, queryset=DatabaseUser.objects)
@ -50,13 +76,14 @@ class DatabaseCreationForm(DatabaseUserCreationForm):
account_id = self.initial.get('account', self.initial_account)
if account_id:
qs = self.fields['user'].queryset.filter(account=account_id).order_by('username')
choices = [ (u.pk, "%s (%s)" % (u, u.get_type_display())) for u in qs ]
choices = [ (u.pk, "%s (%s) (%s)" % (u, u.get_type_display(), str(u.target_server.name) )) for u in qs ]
self.fields['user'].queryset = qs
self.fields['user'].choices = [(None, '--------'),] + choices
def clean_username(self):
username = self.cleaned_data.get('username')
if DatabaseUser.objects.filter(username=username).exists():
server = self.cleaned_data.get('target_server')
if DatabaseUser.objects.filter(username=username, target_server=server).exists():
raise ValidationError("Provided username already exists.")
return username
@ -76,6 +103,9 @@ class DatabaseCreationForm(DatabaseUserCreationForm):
if user and user.type != self.cleaned_data.get('type'):
msg = _("Database type and user type doesn't match")
raise ValidationError(msg)
if user and user.target_server != self.cleaned_data.get('target_server'):
msg = _("Database server and user server doesn't match")
raise ValidationError(msg)
return user
def clean(self):

View file

@ -1,52 +1,46 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
# Generated by Django 2.2.28 on 2023-06-28 17:06
from django.db import models, migrations
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import orchestra.core.validators
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Database',
fields=[
('id', models.AutoField(serialize=False, primary_key=True, verbose_name='ID', auto_created=True)),
('name', models.CharField(verbose_name='name', max_length=64, validators=[orchestra.core.validators.validate_name])),
('type', models.CharField(default='mysql', choices=[('mysql', 'MySQL'), ('postgres', 'PostgreSQL')], verbose_name='type', max_length=32)),
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='databases', verbose_name='Account', to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='DatabaseUser',
fields=[
('id', models.AutoField(serialize=False, primary_key=True, verbose_name='ID', auto_created=True)),
('username', models.CharField(verbose_name='username', max_length=16, validators=[orchestra.core.validators.validate_name])),
('password', models.CharField(verbose_name='password', max_length=256)),
('type', models.CharField(default='mysql', choices=[('mysql', 'MySQL'), ('postgres', 'PostgreSQL')], verbose_name='type', max_length=32)),
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='databaseusers', verbose_name='Account', to=settings.AUTH_USER_MODEL)),
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('username', models.CharField(max_length=16, validators=[orchestra.core.validators.validate_name], verbose_name='username')),
('password', models.CharField(max_length=256, verbose_name='password')),
('type', models.CharField(choices=[('mysql', 'MySQL')], default='mysql', max_length=32, verbose_name='type')),
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='databaseusers', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
],
options={
'verbose_name_plural': 'DB users',
'unique_together': {('username', 'type')},
},
),
migrations.AddField(
model_name='database',
name='users',
field=models.ManyToManyField(related_name='databases', to='databases.DatabaseUser', verbose_name='users', blank=True),
),
migrations.AlterUniqueTogether(
name='databaseuser',
unique_together=set([('username', 'type')]),
),
migrations.AlterUniqueTogether(
name='database',
unique_together=set([('name', 'type')]),
migrations.CreateModel(
name='Database',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=64, validators=[orchestra.core.validators.validate_name], verbose_name='name')),
('type', models.CharField(choices=[('mysql', 'MySQL')], default='mysql', max_length=32, verbose_name='type')),
('comments', models.TextField(blank=True, default='')),
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='databases', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
('users', models.ManyToManyField(blank=True, related_name='databases', to='databases.DatabaseUser', verbose_name='users')),
],
options={
'unique_together': {('name', 'type')},
},
),
]

View file

@ -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'),
),
]

View file

@ -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')},
),
]

View file

@ -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'),
),
]

View file

@ -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')},
),
]

View file

@ -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'),
),
]

View file

@ -1,7 +1,7 @@
import hashlib
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.core import validators
@ -23,9 +23,11 @@ class Database(models.Model):
account = models.ForeignKey('accounts.Account', on_delete=models.CASCADE,
verbose_name=_("Account"), related_name='databases')
comments = models.TextField(default="", blank=True)
target_server = models.ForeignKey('orchestration.Server', on_delete=models.CASCADE,
verbose_name=_("Server"), default=3 )
class Meta:
unique_together = ('name', 'type')
unique_together = ('name', 'type', 'target_server')
def __str__(self):
return "%s" % self.name
@ -54,7 +56,12 @@ class DatabaseUser(models.Model):
MYSQL = Database.MYSQL
POSTGRESQL = Database.POSTGRESQL
username = models.CharField(_("username"), max_length=16, # MySQL usernames 16 char long
typeOfPermision = [
('all','all'),
('ro', 'read only'),
]
username = models.CharField(_("username"), max_length=32, # MySQL usernames 16 char long
validators=[validators.validate_name])
password = models.CharField(_("password"), max_length=256)
type = models.CharField(_("type"), max_length=32,
@ -62,10 +69,14 @@ class DatabaseUser(models.Model):
default=settings.DATABASES_DEFAULT_TYPE)
account = models.ForeignKey('accounts.Account', on_delete=models.CASCADE,
verbose_name=_("Account"), related_name='databaseusers')
target_server = models.ForeignKey('orchestration.Server', on_delete=models.CASCADE,
verbose_name=_("Server"), default=3 )
permision = models.CharField(verbose_name=_("Permisson"), max_length=20, choices=typeOfPermision, default='all')
class Meta:
verbose_name_plural = _("DB users")
unique_together = ('username', 'type')
unique_together = ('username', 'type', 'target_server')
def __str__(self):
return self.username

View file

@ -7,7 +7,7 @@ from django.db.models.functions import Concat, Coalesce
from django.forms.models import modelformset_factory
from django.shortcuts import render
from django.utils.safestring import mark_safe
from django.utils.translation import ungettext, ugettext_lazy as _
from django.utils.translation import ngettext, gettext_lazy as _
from django.template.response import TemplateResponse
from orchestra.admin.utils import get_object_from_url, change_url, admin_link
@ -84,7 +84,7 @@ def edit_records(modeladmin, request, queryset):
change_message = modeladmin.construct_change_message(request, fake_form, [formset])
modeladmin.log_change(request, formset.instance, change_message)
num = len(formsets)
message = ungettext(
message = ngettext(
_("Records for one selected domain have been updated."),
_("Records for %i selected domains have been updated.") % num,
num)
@ -127,7 +127,7 @@ def set_soa(modeladmin, request, queryset):
modeladmin.log_change(request, domain, change_message)
domain.save()
num = len(queryset)
msg = ungettext(
msg = ngettext(
_("SOA record for one domain has been updated."),
_("SOA record for %s domains has been updated.") % num,
num

View file

@ -5,7 +5,7 @@ from django.db.models.functions import Concat, Coalesce
from django.templatetags.static import static
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext, ugettext_lazy as _
from django.utils.translation import gettext, gettext_lazy as _
from orchestra.admin import ExtendedModelAdmin
from orchestra.admin.utils import admin_link, change_url

View file

@ -2,7 +2,7 @@ import re
import socket
import textwrap
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.contrib.orchestration import ServiceController
from orchestra.contrib.orchestration import Operation

View file

@ -1,5 +1,5 @@
from django.contrib.admin import SimpleListFilter
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
class TopDomainListFilter(SimpleListFilter):

View file

@ -1,7 +1,7 @@
from django import forms
from django.core.exceptions import ValidationError
from django.utils.text import capfirst
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.admin.forms import AdminFormSet, AdminFormMixin

View file

@ -1,6 +1,6 @@
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import ungettext, ugettext_lazy as _
from django.utils.translation import ngettext, gettext_lazy as _
from orchestra.core.validators import validate_ipv4_address, validate_ipv6_address, validate_ascii
from orchestra.utils.python import AttrDict
@ -114,7 +114,7 @@ class Domain(models.Model):
def get_description(self):
if self.is_top:
num = self.subdomains.count()
return ungettext(
return ngettext(
_("top domain with one subdomain"),
_("top domain with %d subdomains") % num,
num)
@ -144,6 +144,10 @@ class Domain(models.Model):
tail.append(subdomain)
else:
zone += subdomain.render_records()
###darmengo 2021-03-25 add autoconfig
if self.has_default_mx():
zone += 'autoconfig.{}. 30m IN A 109.69.8.133\n'.format(self.name)
###END darmengo 2021-03-25 add autoconfig
for subdomain in sorted(tail, key=lambda x: len(x.name), reverse=True):
zone += subdomain.render_records()
return zone.strip()

View file

@ -1,5 +1,5 @@
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from orchestra.api.serializers import HyperlinkedModelSerializer

View file

@ -1,5 +1,5 @@
{% extends "admin/change_form.html" %}
{% load i18n admin_urls admin_static admin_modify %}
{% load i18n admin_urls static admin_modify %}
{% block object-tools-items %}

View file

@ -3,7 +3,7 @@ import os
import re
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.core.validators import validate_hostname
from orchestra.utils import paths

View file

@ -1,12 +1,12 @@
from django.contrib import admin
from django.contrib.admin.templatetags.admin_static import static
from django.templatetags.static import static
from django.contrib.admin.templatetags.admin_urls import add_preserved_filters
from django.contrib.admin.utils import unquote
from django.http import HttpResponseRedirect
from django.urls import NoReverseMatch, reverse
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.admin.utils import admin_date, admin_link

View file

@ -2,7 +2,7 @@ import sys
from django.contrib import messages
from django.db import transaction
from django.utils.translation import ungettext, ugettext_lazy as _
from django.utils.translation import ngettext, gettext_lazy as _
from orchestra.admin.decorators import action_with_confirmation
@ -102,7 +102,7 @@ def mark_as_unread(modeladmin, request, queryset):
ticket.mark_as_unread_by(request.user)
modeladmin.log_change(request, ticket, 'Marked as unread')
num = len(queryset)
msg = ungettext(
msg = ngettext(
_("Selected ticket has been marked as unread."),
_("%i selected tickets have been marked as unread.") % num,
num)
@ -116,7 +116,7 @@ def mark_as_read(modeladmin, request, queryset):
ticket.mark_as_read_by(request.user)
modeladmin.log_change(request, ticket, 'Marked as read')
num = len(queryset)
msg = ungettext(
msg = ngettext(
_("Selected ticket has been marked as read."),
_("%i selected tickets have been marked as read.") % num,
num)

View file

@ -1,5 +1,5 @@
from django import forms
from django.conf.urls import url
from django.urls import re_path as url
from django.contrib import admin
from django.urls import reverse
from django.db import models
@ -7,7 +7,7 @@ from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from django.utils.html import format_html, strip_tags
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from markdown import markdown
from orchestra.admin import ExtendedModelAdmin
@ -68,7 +68,7 @@ class MessageReadOnlyInline(admin.TabularInline):
return header + content
content_html.short_description = _("Content")
def has_add_permission(self, request):
def has_add_permission(self, request, obj):
return False
def has_delete_permission(self, request, obj=None):

View file

@ -1,5 +1,5 @@
from django.contrib.admin import SimpleListFilter
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from .models import Ticket

View file

@ -2,7 +2,7 @@ from django import forms
from django.contrib.auth import get_user_model
from django.utils.html import strip_tags
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from django.templatetags.static import static
from markdown import markdown

View file

@ -1,7 +1,7 @@
from django.conf import settings as djsettings
from django.db import models
from django.db.models import query, Q
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.contrib.contacts import settings as contacts_settings
from orchestra.contrib.contacts.models import Contact

View file

@ -1,7 +1,7 @@
from django.contrib import messages, admin
from django.template.response import TemplateResponse
from django.utils.safestring import mark_safe
from django.utils.translation import ungettext, ugettext, ugettext_lazy as _
from django.utils.translation import ngettext, gettext, gettext_lazy as _
from orchestra.admin.utils import admin_link
from orchestra.contrib.orchestration import Operation, helpers
@ -16,12 +16,12 @@ def letsencrypt(modeladmin, request, queryset):
content_error = ''
contentless = queryset.exclude(content__path='/').distinct()
if contentless:
content_error = ungettext(
ugettext("Selected website %s doesn't have a webapp mounted on <tt>/</tt>."),
ugettext("Selected websites %s don't have a webapp mounted on <tt>/</tt>."),
content_error = ngettext(
gettext("Selected website %s doesn't have a webapp mounted on <tt>/</tt>."),
gettext("Selected websites %s don't have a webapp mounted on <tt>/</tt>."),
len(contentless),
)
content_error += ugettext("<br>Websites need a webapp (e.g. static) mounted on </tt>/</tt> "
content_error += gettext("<br>Websites need a webapp (e.g. static) mounted on </tt>/</tt> "
"for let's encrypt HTTP-01 challenge to work.")
content_error = content_error % ', '.join((admin_link()(website) for website in contentless))
content_error = '<ul class="errorlist"><li>%s</li></ul>' % content_error
@ -76,19 +76,19 @@ def letsencrypt(modeladmin, request, queryset):
'no_https': no_https
}
if errors:
msg = ungettext(
msg = ngettext(
_("No lineages found for websites {name}."),
_("No lineages found for {errors} websites."),
errors)
messages.error(request, msg % context)
if successes:
msg = ungettext(
msg = ngettext(
_("{name} website has successfully been encrypted."),
_("{successes} websites have been successfully encrypted."),
successes)
messages.success(request, msg.format(**context))
if no_https:
msg = ungettext(
msg = ngettext(
_("{name} website does not have <b>HTTPS protocol</b> enabled."),
_("{no_https} websites do not have <b>HTTPS protocol</b> enabled."),
no_https)
@ -99,7 +99,7 @@ def letsencrypt(modeladmin, request, queryset):
context = {
'title': _("Let's encrypt!"),
'action_name': _("Encrypt"),
'content_message': ugettext("You are going to request certificates for the following domains.<br>"
'content_message': gettext("You are going to request certificates for the following domains.<br>"
"This operation is safe to run multiple times, "
"existing certificates will not be regenerated. "
"Also notice that let's encrypt does not currently support wildcard certificates.") + content_error,

View file

@ -1,6 +1,6 @@
from django import forms
from django.core.exceptions import ValidationError
from django.utils.translation import ungettext, ugettext_lazy as _
from django.utils.translation import ngettext, gettext_lazy as _
from .helpers import is_valid_domain

View file

@ -1,7 +1,7 @@
from django.contrib import admin
from django.conf.urls import url
from django.urls import re_path as url
from django.contrib.auth.admin import UserAdmin
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
from orchestra.admin.actions import disable, enable
@ -16,7 +16,7 @@ from .filters import HasCustomAddressListFilter
from .models import List
class ListAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedModelAdmin):
class ListAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
list_display = (
'name', 'address_name', 'address_domain_link', 'account_link', 'display_active'
)
@ -31,7 +31,7 @@ class ListAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedModel
}),
(_("Admin"), {
'classes': ('wide',),
'fields': ('admin_email', 'password1', 'password2'),
'fields': ('admin_email',),
}),
)
fieldsets = (
@ -45,35 +45,15 @@ class ListAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedModel
) % settings.LISTS_DEFAULT_DOMAIN,
'fields': (('address_name', 'address_domain'),)
}),
(_("Admin"), {
'classes': ('wide',),
'fields': ('password',),
}),
)
search_fields = ('name', 'address_name', 'address_domain__name', 'account__username')
list_filter = (IsActiveListFilter, HasCustomAddressListFilter)
readonly_fields = ('account_link',)
change_readonly_fields = ('name',)
form = NonStoredUserChangeForm
add_form = UserCreationForm
list_select_related = ('account', 'address_domain',)
filter_by_account_fields = ['address_domain']
actions = (disable, enable, list_accounts)
address_domain_link = admin_link('address_domain', order='address_domain__name')
def get_urls(self):
useradmin = UserAdmin(List, self.admin_site)
return [
url(r'^(\d+)/password/$',
self.admin_site.admin_view(useradmin.user_change_password))
] + super(ListAdmin, self).get_urls()
def save_model(self, request, obj, form, change):
""" set password """
if not change:
obj.set_password(form.cleaned_data["password1"])
super(ListAdmin, self).save_model(request, obj, form, change)
admin.site.register(List, ListAdmin)

View file

@ -1,6 +1,6 @@
import textwrap
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.contrib.orchestration import ServiceController, replace
from orchestra.contrib.resources import ServiceMonitor
@ -18,7 +18,7 @@ class MailmanVirtualDomainController(ServiceController):
doc_settings = (settings,
('LISTS_VIRTUAL_ALIAS_DOMAINS_PATH',)
)
def is_hosted_domain(self, domain):
""" whether or not domain MX points to this server """
return domain.has_default_mx()
@ -48,11 +48,11 @@ class MailmanVirtualDomainController(ServiceController):
def save(self, mail_list):
context = self.get_context(mail_list)
#self.include_virtual_alias_domain(context)
self.include_virtual_alias_domain(context)
def delete(self, mail_list):
context = self.get_context(mail_list)
#self.exclude_virtual_alias_domain(context)
self.exclude_virtual_alias_domain(context)
def commit(self):
context = self.get_context_files()
@ -100,29 +100,70 @@ class MailmanController(MailmanVirtualDomainController):
aliases = ['# %(banner)s' % context]
for suffix in self.address_suffixes:
context['suffix'] = suffix
# Because mailman doesn't properly handle lists aliases we need two virtual aliases
aliases.append("%(address_name)s%(suffix)s@%(domain)s\t%(name)s%(suffix)s@grups.pangea.org" % context)
# Because mailman doesn't properly handle lists aliases we need virtual aliases
if context['address_name'] != context['name']:
# And another with the original list name; Mailman generates links with it
aliases.append("%(name)s%(suffix)s@%(domain)s\t%(name)s%(suffix)s" % context)
aliases.append("%(address_name)s%(suffix)s@%(domain)s\t%(name)s%(suffix)s@grups.pangea.org" % context)
return '\n'.join(aliases)
def save(self, mail_list):
context = self.get_context(mail_list)
# Create list
cmd = "/opt/mailman/venv/bin/python /usr/local/admin/orchestra_mailman3/save.py %(name)s %(admin)s %(address_name)s@%(domain)s" % context
if not mail_list.active:
cmd += ' --inactive'
self.append(cmd)
# Custom domain
if mail_list.address:
context.update({
'aliases': self.get_virtual_aliases(context),
'num_entries': 2 if context['address_name'] != context['name'] else 1,
})
self.append(textwrap.dedent("""\
# Create list alias for custom domain
aliases='%(aliases)s'
if ! grep '\s\s*%(name)s\s*$' %(virtual_alias)s > /dev/null; then
echo "${aliases}" >> %(virtual_alias)s
UPDATED_VIRTUAL_ALIAS=1
else
if grep -E '(%(address_name)s|%(name)s)@(%(address_domain)s|grups.pangea.org)' %(virtual_alias)s > /dev/null ; then
sed -i -e '/^.*%(name)s\(-admin\|-bounces\|-confirm\|-join\|-leave\|-owner\|-request\|-subscribe\|-unsubscribe\|@\).*$/d' \\
-e '/# .*%(name)s$/d' %(virtual_alias)s
echo "${aliases}" >> %(virtual_alias)s
UPDATED_VIRTUAL_ALIAS=1
fi
fi """) % context
)
else:
self.append(textwrap.dedent("""\
# Cleanup possible ex-custom domain
if grep '\s\s*%(name)s\s*$' %(virtual_alias)s > /dev/null; then
#sed -i "/^.*\s%(name)s\s*$/d" %(virtual_alias)s
sed -i -e '/^.*%(name)s\(-admin\|-bounces\|-confirm\|-join\|-leave\|-owner\|-request\|-subscribe\|-unsubscribe\|@\).*$/d' \\
-e '/# .*%(name)s$/d' %(virtual_alias)s
fi""") % context
)
def delete(self, mail_list):
context = self.get_context(mail_list)
# Custom domain delete
self.append(textwrap.dedent("""\
# Cleanup possible ex-custom domain
if grep '\s\s*%(name)s\s*$' %(virtual_alias)s > /dev/null; then
sed -i -e '/^.*%(name)s\(-admin\|-bounces\|-confirm\|-join\|-leave\|-owner\|-request\|-subscribe\|-unsubscribe\|@\).*$/d' \\
-e '/# .*%(name)s$/d' %(virtual_alias)s
fi""") % context
)
# Delete list
cmd = "/opt/mailman/venv/bin/python /usr/local/admin/orchestra_mailman3/delete.py %(name)s %(admin)s %(address_name)s@%(domain)s" % context
if not mail_list.active:
cmd += ' --inactive'
cmd = "/opt/mailman/venv/bin/python /usr/local/admin/orchestra_mailman3/delete.py %(name)s" % context
self.append(cmd)
def commit(self):
pass
@ -141,7 +182,6 @@ class MailmanController(MailmanVirtualDomainController):
context.update({
'banner': self.get_banner(mail_list),
'name': mail_list.name,
'password': mail_list.password,
'domain': mail_list.address_domain or settings.LISTS_DEFAULT_DOMAIN,
'address_name': mail_list.get_address_name(),
'address_domain': mail_list.address_domain,

View file

@ -1,5 +1,5 @@
from django.contrib.admin import SimpleListFilter
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
class HasCustomAddressListFilter(SimpleListFilter):

View file

@ -1,34 +1,34 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
# Generated by Django 2.2.28 on 2023-09-01 14:59
from django.db import models, migrations
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import orchestra.core.validators
class Migration(migrations.Migration):
initial = True
dependencies = [
('domains', '__first__'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('domains', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='List',
fields=[
('id', models.AutoField(auto_created=True, verbose_name='ID', serialize=False, primary_key=True)),
('name', models.CharField(max_length=128, validators=[orchestra.core.validators.validate_name], unique=True, verbose_name='name', help_text='Default list address &lt;name&gt;@lists.orchestra.lan')),
('address_name', models.CharField(max_length=128, validators=[orchestra.core.validators.validate_name], verbose_name='address name', blank=True)),
('admin_email', models.EmailField(max_length=254, verbose_name='admin email', help_text='Administration email address')),
('is_active', models.BooleanField(default=True, verbose_name='active', help_text='Designates whether this account should be treated as active. Unselect this instead of deleting accounts.')),
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(help_text='Default list address &lt;name&gt;@grups.pangea.org', max_length=64, unique=True, validators=[orchestra.core.validators.validate_name], verbose_name='name')),
('address_name', models.CharField(blank=True, max_length=64, validators=[orchestra.core.validators.validate_name], verbose_name='address name')),
('admin_email', models.EmailField(help_text='Administration email address', max_length=254, verbose_name='admin email')),
('is_active', models.BooleanField(default=True, help_text='Designates whether this account should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='lists', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
('address_domain', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, null=True, blank=True, to='domains.Domain', verbose_name='address domain')),
('address_domain', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='domains.Domain', verbose_name='address domain')),
],
),
migrations.AlterUniqueTogether(
name='list',
unique_together=set([('address_name', 'address_domain')]),
options={
'unique_together': {('address_name', 'address_domain')},
},
),
]

View file

@ -1,24 +1,13 @@
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.core.validators import validate_name
from . import settings
class ListQuerySet(models.QuerySet):
def create(self, **kwargs):
""" Sets password if provided, all within a single DB operation """
password = kwargs.pop('password')
instance = self.model(**kwargs)
if password:
instance.set_password(password)
instance.save()
return instance
# TODO address and domain, perhaps allow only domain?
class List(models.Model):
name = models.CharField(_("name"), max_length=64, unique=True, validators=[validate_name],
@ -35,9 +24,6 @@ class List(models.Model):
is_active = models.BooleanField(_("active"), default=True,
help_text=_("Designates whether this account should be treated as active. "
"Unselect this instead of deleting accounts."))
password = None
objects = ListQuerySet.as_manager()
class Meta:
unique_together = ('address_name', 'address_domain')
@ -75,9 +61,6 @@ class List(models.Model):
def get_username(self):
return self.name
def set_password(self, password):
self.password = password
def get_absolute_url(self):
context = {
'name': self.name

View file

@ -1,6 +1,6 @@
from django.core.validators import RegexValidator
from django.forms import widgets
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from orchestra.api.serializers import SetPasswordHyperlinkedSerializer, RelatedHyperlinkedModelSerializer

View file

@ -9,32 +9,33 @@ LISTS_DOMAIN_MODEL = Setting('LISTS_DOMAIN_MODEL',
LISTS_DEFAULT_DOMAIN = Setting('LISTS_DEFAULT_DOMAIN',
'lists.{}'.format(ORCHESTRA_BASE_DOMAIN),
'grups.{}'.format(ORCHESTRA_BASE_DOMAIN),
help_text="Uses <tt>ORCHESTRA_BASE_DOMAIN</tt> by default."
)
LISTS_LIST_URL = Setting('LISTS_LIST_URL',
'https://lists.{}/mailman/listinfo/%(name)s'.format(ORCHESTRA_BASE_DOMAIN),
# 'https://lists.{}/mailman/listinfo/%(name)s'.format(ORCHESTRA_BASE_DOMAIN),
'https://www.{0}/mailman3/lists/%(name)s.{0}'.format(LISTS_DEFAULT_DOMAIN),
help_text="Uses <tt>ORCHESTRA_BASE_DOMAIN</tt> by default."
)
LISTS_MAILMAN_POST_LOG_PATH = Setting('LISTS_MAILMAN_POST_LOG_PATH',
'/var/log/mailman/post'
'/var/log/mailman3/smtp'
)
LISTS_MAILMAN_ROOT_DIR = Setting('LISTS_MAILMAN_ROOT_DIR',
'/var/lib/mailman'
'/var/lib/mailman3'
)
LISTS_VIRTUAL_ALIAS_PATH = Setting('LISTS_VIRTUAL_ALIAS_PATH',
'/etc/postfix/mailman_virtual_aliases'
'/etc/postfix/mailman3_virtusertable'
)
LISTS_VIRTUAL_ALIAS_DOMAINS_PATH = Setting('LISTS_VIRTUAL_ALIAS_DOMAINS_PATH',
'/etc/postfix/mailman_virtual_domains'
'/etc/postfix/mailman3_virtdomains'
)

View file

@ -8,7 +8,7 @@ from django.db.models import F, Count, Value as V
from django.db.models.functions import Concat
from django.utils.html import format_html, format_html_join
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
from orchestra.admin.actions import disable, enable
@ -20,7 +20,7 @@ from orchestra.core import caches
from . import settings
from .actions import SendMailboxEmail, SendAddressEmail
from .filters import HasMailboxListFilter, HasForwardListFilter, HasAddressListFilter
from .filters import HasMailboxListFilter, HasForwardListFilter, HasAddressListFilter, HasTipeServerFilter
from .forms import MailboxCreationForm, MailboxChangeForm, AddressForm
from .models import Mailbox, Address, Autoresponse
from .widgets import OpenCustomFilteringOnSelect
@ -40,7 +40,7 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo
list_display = (
'name', 'account_link', 'display_filtering', 'display_addresses', 'display_active',
)
list_filter = (IsActiveListFilter, HasAddressListFilter, 'filtering')
list_filter = (IsActiveListFilter, HasAddressListFilter, 'filtering', HasTipeServerFilter)
search_fields = (
'account__username', 'account__short_name', 'account__full_name', 'name',
'addresses__name', 'addresses__domain__name',

View file

@ -4,7 +4,7 @@ import re
import textwrap
from django.core.exceptions import ObjectDoesNotExist
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.contrib.orchestration import ServiceController
from orchestra.contrib.resources import ServiceMonitor
@ -437,15 +437,20 @@ class DovecotMaildirDisk(ServiceMonitor):
def prepare(self):
super().prepare()
current_date = self.current_date.strftime("%Y-%m-%d %H:%M:%S %Z")
# self.append(textwrap.dedent("""\
# function monitor () {
# awk 'BEGIN { size = 0 } NR > 1 { size += $1 } END { print size }' $1 || echo 0
# }"""))
self.append(textwrap.dedent("""\
function monitor () {
awk 'BEGIN { size = 0 } NR > 1 { size += $1 } END { print size }' $1 || echo 0
SIZE=$(du -sb $1/Maildir/ 2> /dev/null || echo 0) && echo $SIZE | awk '{print $1}'
}"""))
def monitor(self, mailbox):
context = self.get_context(mailbox)
self.append("echo %(object_id)s $(monitor %(maildir_path)s)" % context)
# self.append("echo %(object_id)s $(monitor %(maildir_path)s)" % context)
self.append("echo %(object_id)s $(monitor %(home)s)" % context)
def get_context(self, mailbox):
context = {
'home': mailbox.get_home(),

View file

@ -1,6 +1,8 @@
from django.contrib.admin import SimpleListFilter
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.contrib.orchestration.models import Server
from orchestra.contrib.websites.models import Website
from orchestra.settings import WEB_SERVERS
class HasMailboxListFilter(SimpleListFilter):
""" Filter addresses whether they have any mailbox or not """
@ -45,3 +47,17 @@ class HasAddressListFilter(HasMailboxListFilter):
elif self.value() == 'False':
return queryset.filter(addresses__isnull=True)
return queryset
class HasTipeServerFilter(SimpleListFilter):
title = _("has type server")
parameter_name = 'has_servers'
def lookups(self, request, model_admin):
return [ (x.id, x.name) for x in Server.objects.filter(name__in=WEB_SERVERS) ]
def queryset(self, request, queryset):
if self.value() is not None:
serverWebsites = Website.objects.filter(target_server=self.value())
return queryset.filter(account__in=[ x.account.id for x in serverWebsites ] )
return queryset

View file

@ -2,7 +2,7 @@ from django import forms
from django.contrib.admin import widgets
from django.core.exceptions import ValidationError
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.forms import UserCreationForm, UserChangeForm
from orchestra.utils.python import AttrDict

View file

@ -6,7 +6,7 @@ from django.contrib.auth.hashers import make_password
from django.core.validators import RegexValidator, ValidationError
from django.db import models
from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from . import validators, settings

View file

@ -3,7 +3,7 @@ import textwrap
from django.utils.functional import lazy
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.contrib.settings import Setting
from orchestra.core.validators import validate_name

View file

@ -3,7 +3,7 @@ import os
import re
from django.core.validators import ValidationError, EmailValidator
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.utils import paths
from orchestra.utils.sys import run

View file

@ -8,7 +8,7 @@ from django.db.models import Count
from django.shortcuts import redirect
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.admin import ExtendedModelAdmin
from orchestra.admin.utils import admin_link, admin_colored, admin_date, wrap_admin_view
@ -115,7 +115,7 @@ class MessageAdmin(ExtendedModelAdmin):
display_to.short_description = _("To")
def get_urls(self):
from django.conf.urls import url
from django.urls import re_path as url
urls = super().get_urls()
info = self.model._meta.app_label, self.model._meta.model_name
urls.insert(0,

View file

@ -1,3 +1,4 @@
import smtplib
from datetime import timedelta
from socket import error as SocketError
@ -5,7 +6,6 @@ from socket import error as SocketError
from django.core.mail import get_connection
from django.db.models import Q
from django.utils import timezone
from django.utils.encoding import smart_str
from orchestra.utils.sys import LockFile, OperationLocked
@ -31,7 +31,7 @@ def send_message(message, connection=None, bulk=settings.MAILER_BULK_MESSAGES):
return
error = None
try:
connection.connection.sendmail(message.from_address, [message.to_address], smart_str(message.content))
connection.connection.sendmail(message.from_address, [message.to_address], message.content.encode())
except (SocketError,
smtplib.SMTPSenderRefused,
smtplib.SMTPRecipientsRefused,

View file

@ -1,5 +1,5 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from . import settings

View file

@ -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

View file

@ -1,5 +1,5 @@
{% extends "admin/change_list.html" %}
{% load i18n admin_urls admin_static admin_list %}
{% load i18n admin_urls static admin_list %}
{% block object-tools-items %}

View file

@ -4,7 +4,7 @@ from django.urls import reverse
from django.db import models
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.admin import ExtendedModelAdmin
from orchestra.admin.actions import disable, enable

View file

@ -1,6 +1,6 @@
from django.db import models
from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.core.validators import validate_name
from orchestra.models.fields import NullableCharField

View file

@ -4,7 +4,7 @@ from django.contrib import messages
from django.contrib.admin import helpers
from django.shortcuts import render
from django.utils.safestring import mark_safe
from django.utils.translation import ungettext, ugettext_lazy as _
from django.utils.translation import ngettext, gettext_lazy as _
from orchestra.admin.utils import get_object_from_url, change_url
from orchestra.contrib.orchestration.helpers import message_user

View file

@ -1,7 +1,7 @@
from django.contrib import admin, messages
from django.utils.html import escape
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.admin import ExtendedModelAdmin, ChangeViewActionsMixin
from orchestra.admin.utils import admin_link, admin_date, admin_colored, display_mono, display_code

View file

@ -4,7 +4,7 @@ from functools import partial
from django.apps import apps
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra import plugins

View file

@ -5,7 +5,7 @@ from django.core.mail import mail_admins
from django.urls import reverse, NoReverseMatch
from django.utils.html import escape
from django.utils.safestring import mark_safe
from django.utils.translation import ungettext, ugettext_lazy as _
from django.utils.translation import ngettext, gettext_lazy as _
from orchestra import settings as orchestra_settings
from orchestra.admin.utils import change_url
@ -125,7 +125,7 @@ def get_messages(logs):
async_url = get_backend_url(async_ids)
async_msg = ''
if run_async:
async_msg = ungettext(
async_msg = ngettext(
_('<a href="{async_url}">{name}</a> is running on the background'),
_('<a href="{async_url}">{run_async} backends</a> are running on the background'),
run_async)
@ -133,7 +133,7 @@ def get_messages(logs):
if total == 1:
msg = _('<a href="{url}">{name}</a> has fail to execute')
else:
msg = ungettext(
msg = ngettext(
_('<a href="{url}">{errors} out of {total} backends</a> has fail to execute'),
_('<a href="{url}">{errors} out of {total} backends</a> have fail to execute'),
errors)
@ -147,13 +147,13 @@ def get_messages(logs):
if total == 1:
msg = _('<a href="{url}">{name}</a> has been executed')
else:
msg = ungettext(
msg = ngettext(
_('<a href="{url}">{successes} out of {total} backends</a> has been executed'),
_('<a href="{url}">{successes} out of {total} backends</a> have been executed'),
successes)
msg += ', ' + str(async_msg)
else:
msg = ungettext(
msg = ngettext(
_('<a href="{url}">{name}</a> has been executed'),
_('<a href="{url}">{total} backends</a> have been executed'),
total)

View file

@ -5,10 +5,10 @@ from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.encoding import force_text
from django.utils.encoding import force_str
from django.utils.functional import cached_property
from django.utils.module_loading import autodiscover_modules
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.core.validators import validate_ip_address, validate_hostname, OrValidator
from orchestra.models.fields import NullableCharField, MultiSelectField
@ -128,7 +128,7 @@ class BackendOperationQuerySet(models.QuerySet):
def create(self, **kwargs):
instance = kwargs.get('instance')
if instance and 'instance_repr' not in kwargs:
kwargs['instance_repr'] = force_text(instance)[:256]
kwargs['instance_repr'] = force_str(instance)[:256]
return super(BackendOperationQuerySet, self).create(**kwargs)
@ -207,7 +207,7 @@ class Route(models.Model):
run_async = models.BooleanField(default=False,
help_text=_("Whether or not block the request/response cycle waitting this backend to "
"finish its execution. Usually you want slave servers to run asynchronously."))
async_actions = MultiSelectField(max_length=256, blank=True,
async_actions = MultiSelectField(max_length=256, blank=True, choices=[],
help_text=_("Specify individual actions to be executed asynchronoulsy."))
# method = models.CharField(_("method"), max_lenght=32, choices=method_choices,
# default=MethodBackend.get_default())

View file

@ -1,6 +1,6 @@
from os import path
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.contrib.settings import Setting

View file

@ -1,14 +1,14 @@
import django.dispatch
pre_action = django.dispatch.Signal()
pre_action = django.dispatch.Signal(providing_args=['backend', 'instance', 'action'])
post_action = django.dispatch.Signal()
post_action = django.dispatch.Signal(providing_args=['backend', 'instance', 'action'])
pre_prepare = django.dispatch.Signal()
pre_prepare = django.dispatch.Signal(providing_args=['backend'])
post_prepare = django.dispatch.Signal()
post_prepare = django.dispatch.Signal(providing_args=['backend'])
pre_commit = django.dispatch.Signal()
pre_commit = django.dispatch.Signal(providing_args=['backend'])
post_commit = django.dispatch.Signal()
post_commit = django.dispatch.Signal(providing_args=['backend'])

View file

@ -3,7 +3,7 @@ from django.urls import reverse
from django.db import transaction
from django.utils import timezone
from django.utils.safestring import mark_safe
from django.utils.translation import ungettext, ugettext_lazy as _
from django.utils.translation import ngettext, gettext_lazy as _
from django.shortcuts import render
from orchestra.admin.utils import change_url
@ -95,7 +95,7 @@ class BillSelectedOrders(object):
url = reverse('admin:bills_bill_changelist')
ids = ','.join([str(b.id) for b in bills])
url += '?id__in=%s' % ids
msg = ungettext(
msg = ngettext(
'<a href="{url}">One bill</a> has been created.',
'<a href="{url}">{num} bills</a> have been created.',
num).format(url=url, num=num)
@ -126,7 +126,7 @@ def mark_as_ignored(modeladmin, request, queryset):
order.mark_as_ignored()
modeladmin.log_change(request, order, 'Marked as ignored')
num = len(queryset)
msg = ungettext(
msg = ngettext(
_("Selected order has been marked as ignored."),
_("%i selected orders have been marked as ignored.") % num,
num)
@ -140,7 +140,7 @@ def mark_as_not_ignored(modeladmin, request, queryset):
order.mark_as_not_ignored()
modeladmin.log_change(request, order, 'Marked as not ignored')
num = len(queryset)
msg = ungettext(
msg = ngettext(
_("Selected order has been marked as not ignored."),
_("%i selected orders have been marked as not ignored.") % num,
num)

View file

@ -6,7 +6,7 @@ from django.db.models import Prefetch
from django.utils import timezone
from django.utils.html import escape, format_html
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.admin import ExtendedModelAdmin
from orchestra.admin.utils import admin_link, admin_date, change_url

View file

@ -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

View file

@ -4,8 +4,8 @@ from django.apps import apps
from django.contrib.admin import SimpleListFilter
from django.db.models import Q, Prefetch, F
from django.utils import timezone
from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import force_str
from django.utils.translation import gettext_lazy as _
from . import settings
from .models import MetricStorage
@ -118,7 +118,7 @@ class IgnoreOrderListFilter(SimpleListFilter):
""" Enable default selection different than All """
for lookup, title in self.lookup_choices:
title = title._proxy____args[0]
selected = self.value() == force_text(lookup)
selected = self.value() == force_str(lookup)
if not selected and title == "Not ignored" and self.value() is None:
selected = True
# end of workaround

View file

@ -2,7 +2,7 @@ from django import forms
from django.contrib.admin import widgets
from django.utils import timezone
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.admin.forms import AdminFormMixin
from orchestra.admin.utils import change_url

View file

@ -9,7 +9,7 @@ from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.models import queryset
from orchestra.utils.python import import_class

View file

@ -1,5 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n l10n staticfiles admin_urls utils orders %}
{% load i18n l10n static admin_urls utils orders %}
{% block extrastyle %}
{{ block.super }}

View file

@ -7,7 +7,7 @@ from django.db import transaction
from django.shortcuts import render, redirect
from django.utils.safestring import mark_safe
from django.utils.text import capfirst
from django.utils.translation import ungettext, ugettext_lazy as _
from django.utils.translation import ngettext, gettext_lazy as _
from orchestra.admin.decorators import action_with_confirmation
from orchestra.admin.utils import change_url
@ -38,11 +38,11 @@ def process_transactions(modeladmin, request, queryset):
opts = modeladmin.model._meta
num = len(queryset)
context = {
'title': ungettext(
'title': ngettext(
_("One selected transaction has been processed."),
_("%s Selected transactions have been processed.") % num,
num),
'content_message': ungettext(
'content_message': ngettext(
_("The following transaction process has been generated, "
"you may want to save it on your computer now."),
_("The following %s transaction processes have been generated, "
@ -63,7 +63,7 @@ def mark_as_executed(modeladmin, request, queryset):
transaction.mark_as_executed()
modeladmin.log_change(request, transaction, _("Executed"))
num = len(queryset)
msg = ungettext(
msg = ngettext(
_("One selected transaction has been marked as executed."),
_("%s selected transactions have been marked as executed.") % num,
num)
@ -79,7 +79,7 @@ def mark_as_secured(modeladmin, request, queryset):
transaction.mark_as_secured()
modeladmin.log_change(request, transaction, _("Secured"))
num = len(queryset)
msg = ungettext(
msg = ngettext(
_("One selected transaction has been marked as secured."),
_("%s selected transactions have been marked as secured.") % num,
num)
@ -95,7 +95,7 @@ def mark_as_rejected(modeladmin, request, queryset):
transaction.mark_as_rejected()
modeladmin.log_change(request, transaction, _("Rejected"))
num = len(queryset)
msg = ungettext(
msg = ngettext(
_("One selected transaction has been marked as rejected."),
_("%s selected transactions have been marked as rejected.") % num,
num)
@ -134,7 +134,7 @@ def mark_process_as_executed(modeladmin, request, queryset):
process.mark_as_executed()
modeladmin.log_change(request, process, _("Executed"))
num = len(queryset)
msg = ungettext(
msg = ngettext(
_("One selected process has been marked as executed."),
_("%s selected processes have been marked as executed.") % num,
num)
@ -150,7 +150,7 @@ def abort(modeladmin, request, queryset):
process.abort()
modeladmin.log_change(request, process, _("Aborted"))
num = len(queryset)
msg = ungettext(
msg = ngettext(
_("One selected process has been aborted."),
_("%s selected processes have been aborted.") % num,
num)
@ -166,7 +166,7 @@ def commit(modeladmin, request, queryset):
transaction.mark_as_rejected()
modeladmin.log_change(request, transaction, _("Rejected"))
num = len(queryset)
msg = ungettext(
msg = ngettext(
_("One selected transaction has been marked as rejected."),
_("%s selected transactions have been marked as rejected.") % num,
num)

View file

@ -3,7 +3,7 @@ from django.urls import reverse
from django.http import HttpResponseRedirect
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.admin import ChangeViewActionsMixin, ExtendedModelAdmin
from orchestra.admin.utils import admin_colored, admin_link, admin_date

View file

@ -1,5 +1,5 @@
from django.contrib import messages
from django.utils.translation import ungettext, ugettext_lazy as _
from django.utils.translation import ngettext, gettext_lazy as _
from .models import Transaction
@ -29,7 +29,7 @@ def post_delete_processes(modeladmin, request, related_transactions):
transaction.save(update_fields=('state', 'modified_at'))
num += 1
modeladmin.log_change(request, transaction, _("Unprocessed"))
messages.success(request, ungettext(
messages.success(request, ngettext(
"One related transaction has been marked as <i>waitting for processing</i>",
"%i related transactions have been marked as <i>waitting for processing</i>." % num,
num

View file

@ -1,5 +1,5 @@
from django import forms
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from orchestra.plugins.forms import PluginDataForm

View file

@ -5,7 +5,7 @@ from io import StringIO
from django import forms
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from django_iban.validators import IBANValidator, IBAN_COUNTRY_CODE_LENGTH
from rest_framework import serializers

View file

@ -1,7 +1,7 @@
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from jsonfield import JSONField
from orchestra.models.fields import PrivateFileField

View file

@ -1,4 +1,4 @@
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from orchestra.contrib.settings import Setting

Some files were not shown because too many files have changed in this diff Show more