Compare commits
86 Commits
django-3.2
...
main
Author | SHA1 | Date |
---|---|---|
Jorge Pastor | 4879eec69e | |
Jorge Pastor | bee347c9f5 | |
Jorge Pastor | 5b6bc35063 | |
Jorge Pastor | c6b5cb1d23 | |
Jorge Pastor | 599b3115dc | |
Jorge Pastor | ff444bdb32 | |
Jorge Pastor | 26497b95b1 | |
Jorge Pastor | ace8af24d5 | |
Jorge Pastor | 33293d2ba8 | |
Jorge Pastor | 20bcb83c83 | |
Jorge Pastor | 14ff506a0d | |
Jorge Pastor | 4ff5abe8f6 | |
Jorge Pastor | 081b094a3d | |
Jorge Pastor | b11ebc5d99 | |
Jorge Pastor | e161a699b9 | |
Jorge Pastor | 58b377ad86 | |
Jorge Pastor | 81b314f21a | |
Jorge Pastor | 2e99b8bccd | |
Jorge Pastor | e15d2acd13 | |
Jorge Pastor | 67c291cb99 | |
Jorge Pastor | 9c1acfaf8a | |
Jorge Pastor | 17e0497ed8 | |
Jorge Pastor | a00d1eff9f | |
Jorge Pastor | 35dd1c64c2 | |
Jorge Pastor | b72af48cd1 | |
Jorge Pastor | cb3e482dfc | |
Jorge Pastor | abbe58bc96 | |
Jorge Pastor | 8cd3605d48 | |
Jorge Pastor | e1d250c35f | |
Jorge Pastor | 281d50acc5 | |
Jorge Pastor | 54c6c59237 | |
Jorge Pastor | 9dc719abcb | |
Jorge Pastor | 0dc4352432 | |
Jorge Pastor | 475df0a2e5 | |
Jorge Pastor | 1ebf30db33 | |
Jorge Pastor | 4f258a9fe0 | |
Jorge Pastor | f3e3d45d60 | |
Jorge Pastor | 898dde9330 | |
Jorge Pastor | ad11f64e52 | |
Jorge Pastor | 142c9f97ae | |
Jorge Pastor | b911e0e89f | |
Jorge Pastor | b896dd2262 | |
Jorge Pastor | 6ff6a75eda | |
Jorge Pastor | 4688605bc6 | |
Jorge Pastor | fa1a130370 | |
Jorge Pastor | 3c3e15d1c5 | |
Jorge Pastor | bb4fc5e267 | |
Jorge Pastor | 60771b7808 | |
Jorge Pastor | 5c0c82d50b | |
Jorge Pastor | ee7cf07294 | |
Jorge Pastor | ba1ceede15 | |
Jorge Pastor | c80295c277 | |
Jorge Pastor | 1724309769 | |
Jorge Pastor | d29ffa900d | |
Jorge Pastor | ae88cc4911 | |
Jorge Pastor | 3063e78dd9 | |
Jorge Pastor | 39267baaad | |
Jorge Pastor | 15fe9fa8cf | |
Jorge Pastor | e1edd4f546 | |
Jorge Pastor | 2b635be17e | |
Jorge Pastor | 84880401ea | |
Jorge Pastor | 666126e2de | |
Jorge Pastor | c47e5ac8f3 | |
Jorge Pastor | 3d798f0cbb | |
Jorge Pastor | 16f1d20be2 | |
Jorge Pastor | 6ad5c29035 | |
Jorge Pastor | a717969926 | |
Santiago L | ee9416d8ed | |
Santiago L | 156ab51f33 | |
Santiago L | 75d743cab2 | |
Santiago L | 849af04e4b | |
Santiago L | aea944a732 | |
Santiago L | 5836d6e6ed | |
Santiago L | b21bc1363d | |
Santiago L | 52ec1660f6 | |
Santiago L | 0695099980 | |
Santiago L | 0b31049f0b | |
Santiago L | 1bd7023fdf | |
Santiago L | 40cb2b45bb | |
Jorge Pastor | 01f8ac5481 | |
Jorge Pastor | 7ec7d18544 | |
Jorge Pastor | 4cfbf57428 | |
Jorge Pastor | dc2927bc88 | |
Jorge Pastor | 3d8fddfd9e | |
Jorge Pastor | 031a290390 | |
Jorge Pastor | 1716ea36d0 |
|
@ -1,13 +1,12 @@
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.core.exceptions import PermissionDenied
|
|
||||||
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 gettext_lazy as _
|
from django.utils.translation import ngettext, gettext_lazy as _
|
||||||
from django.utils.translation import ngettext
|
|
||||||
|
|
||||||
from .. import settings
|
from .. import settings
|
||||||
|
|
||||||
from .decorators import action_with_confirmation
|
from .decorators import action_with_confirmation
|
||||||
from .forms import SendEmailForm
|
from .forms import SendEmailForm
|
||||||
|
|
||||||
|
@ -38,7 +37,7 @@ class SendEmail(object):
|
||||||
|
|
||||||
def write_email(self, request):
|
def write_email(self, request):
|
||||||
if not request.user.is_superuser:
|
if not request.user.is_superuser:
|
||||||
raise PermissionDenied()
|
raise PermissionDenied
|
||||||
initial={
|
initial={
|
||||||
'email_from': self.default_from,
|
'email_from': self.default_from,
|
||||||
'to': ' '.join(self.get_email_addresses())
|
'to': ' '.join(self.get_email_addresses())
|
||||||
|
@ -132,19 +131,15 @@ def base_disable(modeladmin, request, queryset, disable=True):
|
||||||
modeladmin.message_user(request, msg)
|
modeladmin.message_user(request, msg)
|
||||||
|
|
||||||
|
|
||||||
@admin.action(
|
|
||||||
description=_("Disable")
|
|
||||||
)
|
|
||||||
@action_with_confirmation()
|
@action_with_confirmation()
|
||||||
def disable(modeladmin, request, queryset):
|
def disable(modeladmin, request, queryset):
|
||||||
return base_disable(modeladmin, request, queryset)
|
return base_disable(modeladmin, request, queryset)
|
||||||
disable.url_name = 'disable'
|
disable.url_name = 'disable'
|
||||||
|
disable.short_description = _("Disable")
|
||||||
|
|
||||||
|
|
||||||
@admin.action(
|
|
||||||
description=_("Enable")
|
|
||||||
)
|
|
||||||
@action_with_confirmation()
|
@action_with_confirmation()
|
||||||
def enable(modeladmin, request, queryset):
|
def enable(modeladmin, request, queryset):
|
||||||
return base_disable(modeladmin, request, queryset, disable=False)
|
return base_disable(modeladmin, request, queryset, disable=False)
|
||||||
enable.url_name = 'enable'
|
enable.url_name = 'enable'
|
||||||
|
enable.short_description = _("Enable")
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
from urllib import parse
|
from urllib import parse
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
|
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
|
||||||
from django.contrib.auth import update_session_auth_hash
|
from django.contrib.auth import update_session_auth_hash
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
|
from django.http import HttpResponseRedirect, Http404, HttpResponse
|
||||||
from django.forms.models import BaseInlineFormSet
|
from django.forms.models import BaseInlineFormSet
|
||||||
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
|
||||||
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.urls import re_path as url
|
|
||||||
from django.utils.decorators import method_decorator
|
from django.utils.decorators import method_decorator
|
||||||
from django.utils.encoding import force_str
|
from django.utils.encoding import force_str
|
||||||
from django.utils.html import escape
|
from django.utils.html import escape
|
||||||
|
@ -19,12 +19,14 @@ 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
|
||||||
|
|
||||||
from ..utils.python import pairwise, random_ascii
|
from ..utils.python import random_ascii, pairwise
|
||||||
|
|
||||||
from .forms import AdminPasswordChangeForm
|
from .forms import AdminPasswordChangeForm
|
||||||
#, AdminRawPasswordChangeForm
|
#, AdminRawPasswordChangeForm
|
||||||
#from django.contrib.auth.forms import AdminPasswordChangeForm
|
#from django.contrib.auth.forms import AdminPasswordChangeForm
|
||||||
from .utils import action_to_view
|
from .utils import action_to_view
|
||||||
|
|
||||||
|
|
||||||
sensitive_post_parameters_m = method_decorator(sensitive_post_parameters())
|
sensitive_post_parameters_m = method_decorator(sensitive_post_parameters())
|
||||||
|
|
||||||
|
|
||||||
|
@ -254,7 +256,7 @@ class ChangePasswordAdminMixin(object):
|
||||||
@sensitive_post_parameters_m
|
@sensitive_post_parameters_m
|
||||||
def change_password(self, request, id, form_url=''):
|
def change_password(self, request, id, form_url=''):
|
||||||
if not self.has_change_permission(request):
|
if not self.has_change_permission(request):
|
||||||
raise PermissionDenied()
|
raise PermissionDenied
|
||||||
# TODO use this insetad of self.get_object(), in other places
|
# TODO use this insetad of self.get_object(), in other places
|
||||||
obj = get_object_or_404(self.get_queryset(request), pk=id)
|
obj = get_object_or_404(self.get_queryset(request), pk=id)
|
||||||
raw = request.GET.get('raw', '0') == '1'
|
raw = request.GET.get('raw', '0') == '1'
|
||||||
|
@ -332,6 +334,6 @@ class ChangePasswordAdminMixin(object):
|
||||||
|
|
||||||
def show_hash(self, request, id):
|
def show_hash(self, request, id):
|
||||||
if not request.user.is_superuser:
|
if not request.user.is_superuser:
|
||||||
raise PermissionDenied()
|
raise PermissionDenied
|
||||||
obj = get_object_or_404(self.get_queryset(request), pk=id)
|
obj = get_object_or_404(self.get_queryset(request), pk=id)
|
||||||
return HttpResponse(obj.password)
|
return HttpResponse(obj.password)
|
||||||
|
|
|
@ -145,8 +145,6 @@ DATABASES = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
|
|
||||||
|
|
||||||
|
|
||||||
# Password validation
|
# Password validation
|
||||||
# https://docs.djangoproject.com/en/{{ docs_version }}/ref/settings/#auth-password-validators
|
# https://docs.djangoproject.com/en/{{ docs_version }}/ref/settings/#auth-password-validators
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from django.urls import include, path
|
from django.conf.urls import include, url
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', include('orchestra.urls')),
|
url(r'', include('orchestra.urls')),
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
default_app_config = 'orchestra.contrib.accounts.apps.AccountConfig'
|
|
@ -29,7 +29,6 @@ from .models import Account
|
||||||
from .filters import HasTipeServerFilter
|
from .filters import HasTipeServerFilter
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Account)
|
|
||||||
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 = (
|
||||||
|
@ -151,6 +150,7 @@ class AccountAdmin(ChangePasswordAdminMixin, auth.UserAdmin, ExtendedModelAdmin)
|
||||||
return actions
|
return actions
|
||||||
|
|
||||||
|
|
||||||
|
admin.site.register(Account, AccountAdmin)
|
||||||
|
|
||||||
|
|
||||||
class AccountListAdmin(AccountAdmin):
|
class AccountListAdmin(AccountAdmin):
|
||||||
|
@ -159,10 +159,6 @@ class AccountListAdmin(AccountAdmin):
|
||||||
actions = None
|
actions = None
|
||||||
change_list_template = 'admin/accounts/account/select_account_list.html'
|
change_list_template = 'admin/accounts/account/select_account_list.html'
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("account"),
|
|
||||||
ordering='username',
|
|
||||||
)
|
|
||||||
@mark_safe
|
@mark_safe
|
||||||
def select_account(self, instance):
|
def select_account(self, instance):
|
||||||
# TODO get query string from request.META['QUERY_STRING'] to preserve filters
|
# TODO get query string from request.META['QUERY_STRING'] to preserve filters
|
||||||
|
@ -172,6 +168,8 @@ class AccountListAdmin(AccountAdmin):
|
||||||
'plus': '<strong style="color:green; font-size:12px">+</strong>',
|
'plus': '<strong style="color:green; font-size:12px">+</strong>',
|
||||||
}
|
}
|
||||||
return _('<a href="%(url)s">%(plus)s Add to %(name)s</a>') % context
|
return _('<a href="%(url)s">%(plus)s Add to %(name)s</a>') % context
|
||||||
|
select_account.short_description = _("account")
|
||||||
|
select_account.admin_order_field = 'username'
|
||||||
|
|
||||||
def changelist_view(self, request, extra_context=None):
|
def changelist_view(self, request, extra_context=None):
|
||||||
app_label = request.META['PATH_INFO'].split('/')[-5]
|
app_label = request.META['PATH_INFO'].split('/')[-5]
|
||||||
|
@ -210,10 +208,6 @@ class AccountAdminMixin(object):
|
||||||
account = None
|
account = None
|
||||||
list_select_related = ('account',)
|
list_select_related = ('account',)
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("active"),
|
|
||||||
ordering='is_active',
|
|
||||||
)
|
|
||||||
@mark_safe
|
@mark_safe
|
||||||
def display_active(self, instance):
|
def display_active(self, instance):
|
||||||
if not instance.is_active:
|
if not instance.is_active:
|
||||||
|
@ -222,14 +216,14 @@ class AccountAdminMixin(object):
|
||||||
msg = _("Account disabled")
|
msg = _("Account disabled")
|
||||||
return '<img style="width:13px" src="%s" alt="False" title="%s">' % (static('admin/img/inline-delete.svg'), msg)
|
return '<img style="width:13px" src="%s" alt="False" title="%s">' % (static('admin/img/inline-delete.svg'), msg)
|
||||||
return '<img src="%s" alt="False">' % static('admin/img/icon-yes.svg')
|
return '<img src="%s" alt="False">' % static('admin/img/icon-yes.svg')
|
||||||
|
display_active.short_description = _("active")
|
||||||
|
display_active.admin_order_field = 'is_active'
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("account"),
|
|
||||||
ordering='account__username',
|
|
||||||
)
|
|
||||||
def account_link(self, instance):
|
def account_link(self, instance):
|
||||||
account = instance.account if instance.pk else self.account
|
account = instance.account if instance.pk else self.account
|
||||||
return admin_link()(account)
|
return admin_link()(account)
|
||||||
|
account_link.short_description = _("account")
|
||||||
|
account_link.admin_order_field = 'account__username'
|
||||||
|
|
||||||
def get_form(self, request, obj=None, **kwargs):
|
def get_form(self, request, obj=None, **kwargs):
|
||||||
""" Warns user when object's account is disabled """
|
""" Warns user when object's account is disabled """
|
||||||
|
|
|
@ -1,39 +1,40 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.5 on 2021-04-22 11:08
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
import django.contrib.auth.models
|
||||||
import django.core.validators
|
import django.core.validators
|
||||||
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
import django.utils.timezone
|
import django.utils.timezone
|
||||||
import django.contrib.auth.models
|
import orchestra.contrib.accounts.models
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
# Permissions and contenttypes
|
|
||||||
('auth', '0006_require_contenttypes_0002'),
|
|
||||||
('systemusers', '0001_initial'),
|
('systemusers', '0001_initial'),
|
||||||
|
('auth', '0006_require_contenttypes_0002'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Account',
|
name='Account',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('password', models.CharField(verbose_name='password', max_length=128)),
|
('password', models.CharField(max_length=128, verbose_name='password')),
|
||||||
('last_login', models.DateTimeField(blank=True, verbose_name='last login', null=True)),
|
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
|
||||||
('username', models.CharField(help_text='Required. 64 characters or fewer. Letters, digits and ./-/_ only.', unique=True, validators=[django.core.validators.RegexValidator('^[\\w.-]+$', 'Enter a valid username.', 'invalid')], max_length=32, verbose_name='username')),
|
('username', models.CharField(help_text='Required. 64 characters or fewer. Letters, digits and ./-/_ only.', max_length=32, unique=True, validators=[django.core.validators.RegexValidator('^[\\w.-]+$', 'Enter a valid username.', 'invalid')], verbose_name='username')),
|
||||||
('short_name', models.CharField(blank=True, verbose_name='short name', max_length=64)),
|
('short_name', models.CharField(blank=True, max_length=64, verbose_name='short name')),
|
||||||
('full_name', models.CharField(verbose_name='full name', max_length=256)),
|
('full_name', models.CharField(max_length=256, verbose_name='full name')),
|
||||||
('email', models.EmailField(help_text='Used for password recovery', max_length=254, verbose_name='email address')),
|
('email', models.EmailField(help_text='Used for password recovery', max_length=254, verbose_name='email address')),
|
||||||
('type', models.CharField(verbose_name='type', choices=[('INDIVIDUAL', 'Individual'), ('ASSOCIATION', 'Association'), ('CUSTOMER', 'Customer'), ('COMPANY', 'Company'), ('PUBLICBODY', 'Public body'), ('STAFF', 'Staff'), ('FRIEND', 'Friend')], max_length=32, default='INDIVIDUAL')),
|
('type', models.CharField(choices=[('INDIVIDUAL', 'Individual'), ('ASSOCIATION', 'Association'), ('CUSTOMER', 'Customer'), ('COMPANY', 'Company'), ('PUBLICBODY', 'Public body'), ('STAFF', 'Staff'), ('FRIEND', 'Friend')], default='INDIVIDUAL', max_length=32, verbose_name='type')),
|
||||||
('language', models.CharField(verbose_name='language', choices=[('EN', 'English')], max_length=2, default='EN')),
|
('language', models.CharField(choices=[('EN', 'English')], default='EN', max_length=2, verbose_name='language')),
|
||||||
('comments', models.TextField(blank=True, verbose_name='comments', max_length=256)),
|
('comments', models.TextField(blank=True, max_length=256, verbose_name='comments')),
|
||||||
('is_superuser', models.BooleanField(help_text='Designates that this user has all permissions without explicitly assigning them.', default=False, verbose_name='superuser status')),
|
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
|
||||||
('is_active', models.BooleanField(help_text='Designates whether this account should be treated as active. Unselect this instead of deleting accounts.', default=True, verbose_name='active')),
|
('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')),
|
||||||
('date_joined', models.DateTimeField(verbose_name='date joined', default=django.utils.timezone.now)),
|
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
|
||||||
('main_systemuser', models.ForeignKey(to='systemusers.SystemUser', editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='accounts_main')),
|
('main_systemuser', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='accounts_main', to='systemusers.SystemUser')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'abstract': False,
|
'abstract': False,
|
||||||
|
@ -42,4 +43,40 @@ class Migration(migrations.Migration):
|
||||||
('objects', django.contrib.auth.models.UserManager()),
|
('objects', django.contrib.auth.models.UserManager()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
migrations.AlterModelManagers(
|
||||||
|
name='account',
|
||||||
|
managers=[
|
||||||
|
('objects', orchestra.contrib.accounts.models.AccountManager()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='account',
|
||||||
|
name='language',
|
||||||
|
field=models.CharField(choices=[('CA', 'Catalan'), ('ES', 'Spanish'), ('EN', 'English')], default='CA', max_length=2, verbose_name='language'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='account',
|
||||||
|
name='type',
|
||||||
|
field=models.CharField(choices=[('INDIVIDUAL', 'Individual'), ('ASSOCIATION', 'Association'), ('CUSTOMER', 'Customer'), ('STAFF', 'Staff'), ('FRIEND', 'Friend')], default='INDIVIDUAL', max_length=32, verbose_name='type'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='account',
|
||||||
|
name='username',
|
||||||
|
field=models.CharField(help_text='Required. 32 characters or fewer. Letters, digits and ./-/_ only.', max_length=32, unique=True, validators=[django.core.validators.RegexValidator('^[\\w.-]+$', 'Enter a valid username.', 'invalid')], verbose_name='username'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='account',
|
||||||
|
name='language',
|
||||||
|
field=models.CharField(choices=[('EN', 'English')], default='EN', max_length=2, verbose_name='language'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='account',
|
||||||
|
name='type',
|
||||||
|
field=models.CharField(choices=[('INDIVIDUAL', 'Individual'), ('ASSOCIATION', 'Association'), ('CUSTOMER', 'Customer'), ('COMPANY', 'Company'), ('PUBLICBODY', 'Public body'), ('STAFF', 'Staff'), ('FRIEND', 'Friend')], default='INDIVIDUAL', max_length=32, verbose_name='type'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='account',
|
||||||
|
name='main_systemuser',
|
||||||
|
field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='accounts_main', to='systemusers.SystemUser'),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.10.5 on 2021-04-22 11:08
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
import django.contrib.auth.models
|
|
||||||
import django.core.validators
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
import django.utils.timezone
|
|
||||||
import orchestra.contrib.accounts.models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
replaces = [('accounts', '0001_initial'), ('accounts', '0002_auto_20170528_2005'), ('accounts', '0003_auto_20210330_1049'), ('accounts', '0004_auto_20210422_1108')]
|
|
||||||
|
|
||||||
initial = True
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('systemusers', '0001_initial'),
|
|
||||||
('auth', '0006_require_contenttypes_0002'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Account',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('password', models.CharField(max_length=128, verbose_name='password')),
|
|
||||||
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
|
|
||||||
('username', models.CharField(help_text='Required. 64 characters or fewer. Letters, digits and ./-/_ only.', max_length=32, unique=True, validators=[django.core.validators.RegexValidator('^[\\w.-]+$', 'Enter a valid username.', 'invalid')], verbose_name='username')),
|
|
||||||
('short_name', models.CharField(blank=True, max_length=64, verbose_name='short name')),
|
|
||||||
('full_name', models.CharField(max_length=256, verbose_name='full name')),
|
|
||||||
('email', models.EmailField(help_text='Used for password recovery', max_length=254, verbose_name='email address')),
|
|
||||||
('type', models.CharField(choices=[('INDIVIDUAL', 'Individual'), ('ASSOCIATION', 'Association'), ('CUSTOMER', 'Customer'), ('COMPANY', 'Company'), ('PUBLICBODY', 'Public body'), ('STAFF', 'Staff'), ('FRIEND', 'Friend')], default='INDIVIDUAL', max_length=32, verbose_name='type')),
|
|
||||||
('language', models.CharField(choices=[('EN', 'English')], default='EN', max_length=2, verbose_name='language')),
|
|
||||||
('comments', models.TextField(blank=True, max_length=256, verbose_name='comments')),
|
|
||||||
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
|
|
||||||
('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')),
|
|
||||||
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
|
|
||||||
('main_systemuser', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='accounts_main', to='systemusers.SystemUser')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'abstract': False,
|
|
||||||
},
|
|
||||||
managers=[
|
|
||||||
('objects', django.contrib.auth.models.UserManager()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.AlterModelManagers(
|
|
||||||
name='account',
|
|
||||||
managers=[
|
|
||||||
('objects', orchestra.contrib.accounts.models.AccountManager()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='account',
|
|
||||||
name='language',
|
|
||||||
field=models.CharField(choices=[('CA', 'Catalan'), ('ES', 'Spanish'), ('EN', 'English')], default='CA', max_length=2, verbose_name='language'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='account',
|
|
||||||
name='type',
|
|
||||||
field=models.CharField(choices=[('INDIVIDUAL', 'Individual'), ('ASSOCIATION', 'Association'), ('CUSTOMER', 'Customer'), ('STAFF', 'Staff'), ('FRIEND', 'Friend')], default='INDIVIDUAL', max_length=32, verbose_name='type'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='account',
|
|
||||||
name='username',
|
|
||||||
field=models.CharField(help_text='Required. 32 characters or fewer. Letters, digits and ./-/_ only.', max_length=32, unique=True, validators=[django.core.validators.RegexValidator('^[\\w.-]+$', 'Enter a valid username.', 'invalid')], verbose_name='username'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='account',
|
|
||||||
name='language',
|
|
||||||
field=models.CharField(choices=[('EN', 'English')], default='EN', max_length=2, verbose_name='language'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='account',
|
|
||||||
name='type',
|
|
||||||
field=models.CharField(choices=[('INDIVIDUAL', 'Individual'), ('ASSOCIATION', 'Association'), ('CUSTOMER', 'Customer'), ('COMPANY', 'Company'), ('PUBLICBODY', 'Public body'), ('STAFF', 'Staff'), ('FRIEND', 'Friend')], default='INDIVIDUAL', max_length=32, verbose_name='type'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='account',
|
|
||||||
name='main_systemuser',
|
|
||||||
field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='accounts_main', to='systemusers.SystemUser'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,38 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.10.5 on 2017-05-28 18:05
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
import django.core.validators
|
|
||||||
from django.db import migrations, models
|
|
||||||
import orchestra.contrib.accounts.models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('accounts', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterModelManagers(
|
|
||||||
name='account',
|
|
||||||
managers=[
|
|
||||||
('objects', orchestra.contrib.accounts.models.AccountManager()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='account',
|
|
||||||
name='language',
|
|
||||||
field=models.CharField(choices=[('CA', 'Catalan'), ('ES', 'Spanish'), ('EN', 'English')], default='CA', max_length=2, verbose_name='language'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='account',
|
|
||||||
name='type',
|
|
||||||
field=models.CharField(choices=[('INDIVIDUAL', 'Individual'), ('ASSOCIATION', 'Association'), ('CUSTOMER', 'Customer'), ('STAFF', 'Staff'), ('FRIEND', 'Friend')], default='INDIVIDUAL', max_length=32, verbose_name='type'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='account',
|
|
||||||
name='username',
|
|
||||||
field=models.CharField(help_text='Required. 32 characters or fewer. Letters, digits and ./-/_ only.', max_length=32, unique=True, validators=[django.core.validators.RegexValidator('^[\\w.-]+$', 'Enter a valid username.', 'invalid')], verbose_name='username'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,6 +1,4 @@
|
||||||
# -*- coding: utf-8 -*-
|
# Generated by Django 2.2.24 on 2024-07-11 12:25
|
||||||
# Generated by Django 1.10.5 on 2021-03-30 10:49
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
@ -8,18 +6,18 @@ from django.db import migrations, models
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('accounts', '0002_auto_20170528_2005'),
|
('accounts', '0001_initial'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='account',
|
model_name='account',
|
||||||
name='language',
|
name='language',
|
||||||
field=models.CharField(choices=[('EN', 'English')], default='EN', max_length=2, verbose_name='language'),
|
field=models.CharField(choices=[('CA', 'Catalan'), ('ES', 'Spanish'), ('EN', 'English')], default='CA', max_length=2, verbose_name='language'),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='account',
|
model_name='account',
|
||||||
name='type',
|
name='type',
|
||||||
field=models.CharField(choices=[('INDIVIDUAL', 'Individual'), ('ASSOCIATION', 'Association'), ('CUSTOMER', 'Customer'), ('COMPANY', 'Company'), ('PUBLICBODY', 'Public body'), ('STAFF', 'Staff'), ('FRIEND', 'Friend')], default='INDIVIDUAL', max_length=32, verbose_name='type'),
|
field=models.CharField(choices=[('INDIVIDUAL', 'Individual'), ('ASSOCIATION', 'Association'), ('CUSTOMER', 'Customer'), ('STAFF', 'Staff'), ('FRIEND', 'Friend')], default='INDIVIDUAL', max_length=32, verbose_name='type'),
|
||||||
),
|
),
|
||||||
]
|
]
|
|
@ -0,0 +1,42 @@
|
||||||
|
BBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
|
||||||
|
BBBB BBBB BBBBBBBBBB BBBBBB BBBBBBBBBBBB
|
||||||
|
|
||||||
|
|
||||||
|
BBBBB BBBBBBBBBBB
|
||||||
|
XXXX XXXXXXXXXXXXXXXXXXXX
|
||||||
|
XX XXXXXXBBB BBBBBBBBBBBBBXX gettext(u'Home') XXXX
|
||||||
|
BB BBBBBBBBBBBB
|
||||||
|
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXXXXX
|
||||||
|
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXFFFFFFFFXXXX
|
||||||
|
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBXXFFFFFFFFFFFFFFFFFFXXXX
|
||||||
|
BBBB
|
||||||
|
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBXXXXXX
|
||||||
|
XXXXXXXX BB BBBBBBBBBBBBBBBBBBBBBXX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXFFFFFFFFXXXXBBBBFFFFFFFFBBBBB
|
||||||
|
BBBBB
|
||||||
|
BB BBBBBBBBBBB
|
||||||
|
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXX gettext(u'Select %(name)s account') SSSSSS SSSSSSSS SSSSSSSXXXX
|
||||||
|
BBBBB
|
||||||
|
XXXXXXXX BB BBB gettext(u'Add') BBBBFFFFFFFFFFFFFFFFFFBBBBB
|
||||||
|
XXXXXX
|
||||||
|
BBBBBBBB
|
||||||
|
|
||||||
|
|
||||||
|
BBBBB BBBBBBBBBBBBBBBBBB
|
||||||
|
BB BBBBBBBB
|
||||||
|
XXXXXXXXXXX XXXXXXXXXXXX XXXXXXXXXXXXXXXXXX X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXX XXXX X X XXXX
|
||||||
|
XXXXXXX XXXXXXXX XXXXXXXXX gettext(u'Services') XXXXXXXXX
|
||||||
|
BBB BBBBBBB BB BBBBBBBB
|
||||||
|
XXXXXXX XXXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXXXXXXXXXXFFFFFFFFXXXXXXXXX
|
||||||
|
BBBBBB
|
||||||
|
XXXXXXXXXXXXXX
|
||||||
|
BBBBB
|
||||||
|
BB BBBBBBBB
|
||||||
|
XXXXXXXXXXX XXXXXXXXXXXX XXXXXXXXXXXXXXXXXX X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXX XXXX XXX XXX XXXXXX
|
||||||
|
XXXXXXX XXXXXXXX XXXXXXXXX gettext(u'Accounts') XXXXXXXXX
|
||||||
|
BBB BBBBBBB BB BBBBBBBB
|
||||||
|
XXXXXXX XXXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXXXXXXXXXXFFFFFFFFXXXXXXXXX
|
||||||
|
BBBBBB
|
||||||
|
XXXXXXXXXXXXXX
|
||||||
|
BBBBB
|
||||||
|
|
||||||
|
BBBBBBBB
|
|
@ -0,0 +1,49 @@
|
||||||
|
BBBBBBB BBBBBBBBBBBBBBBBBBBBBBBB
|
||||||
|
BBBB BBBB BBBBBBBBBB BBBBBBBBBB
|
||||||
|
|
||||||
|
|
||||||
|
BBBBB BBBBBBBBBBB
|
||||||
|
XXXX XXXXXXXXXXXXXXXXXXXX
|
||||||
|
XX XXXXXXBBB BBBBBBBBBBBBBXX gettext(u'Home') XXXX
|
||||||
|
BB BBBBBBB
|
||||||
|
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXXXXX
|
||||||
|
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXFFFFFFFFXXXX
|
||||||
|
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBXXFFFFFFFFFFFFFFFFFFXXXX
|
||||||
|
BBBB
|
||||||
|
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBXXXXXX
|
||||||
|
BBBBB
|
||||||
|
XXXXXXXX FFFFFFFF
|
||||||
|
XXXXXX
|
||||||
|
BBBBBBBB
|
||||||
|
|
||||||
|
|
||||||
|
BBBBB BBBBBBBBBBBBBBBBBB
|
||||||
|
XXXX
|
||||||
|
BBB BBBBBBBBBBBBBBBBBBBBBBBBBBB BB BBBBBBB
|
||||||
|
XX XXXXXXBBBBBBBBBBBBBBBBBBBBB BBBBBBB BBBBBBBB BBBBBBBBX XXXXXXXXXXXXXXXX
|
||||||
|
BB BBBBBBBBBBBB
|
||||||
|
gettext(u'Add %(name)s') SSS SSSSSSSS
|
||||||
|
BBBB
|
||||||
|
gettext(u'Add %(account)s %(name)s') SSS SSSSSSSSSSS SSSSSSSS
|
||||||
|
BBBBB
|
||||||
|
XXXX
|
||||||
|
XXXXX
|
||||||
|
BBBBBBBB
|
||||||
|
|
||||||
|
|
||||||
|
BBBBB BBBBBBB
|
||||||
|
BB BBBBBBBBBBBBBB
|
||||||
|
XXXX XXXXXXXXXXXXXXXXXXXXXXX
|
||||||
|
XXXX gettext(u'Filter') XXXXX
|
||||||
|
BB BBBBBBB
|
||||||
|
XXXX gettext(u'By account') XXXXX
|
||||||
|
XXXX
|
||||||
|
XXX BB BBB BBBBBBBBBBBBXXXXXXXXXXXXXXXXBBBBBXXX XXXXXXXXXXXXXXXXXFFFFFFFFFFFFFFFFFFXXXXXXXXX
|
||||||
|
XXX BB BBBBBBBBBBBBXXXXXXXXXXXXXXXXBBBBBXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||||
|
XXXXX
|
||||||
|
BBBBB
|
||||||
|
BBB BBBB BB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BB BBBBBBBBBB
|
||||||
|
XXXXXX
|
||||||
|
BBBBB
|
||||||
|
BBBBBBBB
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
BBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
|
||||||
|
BBBB BBBB BBBB BBBBBBBBBB
|
||||||
|
|
||||||
|
BBBBB BBBBBBB
|
||||||
|
BB BBBBBBBBBBBBB
|
||||||
|
XXX gettext(u"Deleting the selected %(objects_name)s would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:") SSSSSSSS SSS SSSSSSSS SSSSSSSSSSSSSSSS SSSSS SSSSSS SS SSSSSSSS SSSSSSS SSSSSSSS SSS SSSS SSSSSSS SSSSSSS SSSS SSSSSSSSSS SS SSSSSS SSS SSSSSSSSS SSSSS SS SSSSSSSSXXXX
|
||||||
|
XXXX
|
||||||
|
BBB BBB BB BBBBBBBBBBBBB
|
||||||
|
XXXXXXXXX
|
||||||
|
BBBBBB
|
||||||
|
XXXXX
|
||||||
|
BBBB BBBBBBBBB
|
||||||
|
XXX gettext(u'Deleting the selected %(objects_name)s would require deleting the following protected related objects:') SSSSSSSS SSS SSSSSSSS SSSSSSSSSSSSSSSS SSSSS SSSSSSS SSSSSSSS SSS SSSSSSSSS SSSSSSSSS SSSSSSS SSSSSSSSXXXX
|
||||||
|
XXXX
|
||||||
|
BBB BBB BB BBBBBBBBB
|
||||||
|
XXXXXXXXX
|
||||||
|
BBBBBB
|
||||||
|
XXXXX
|
||||||
|
BBBB
|
||||||
|
XXX gettext(u'Are you sure you want to delete the selected %(objects_name)s? All of the following objects and their related items will be deleted:') SSS SSS SSSS SSS SSSS SS SSSSSS SSS SSSSSSSS SSSSSSSSSSSSSSSSS SSS SS SSS SSSSSSSSS SSSSSSS SSS SSSSS SSSSSSS SSSSS SSSS SS SSSSSSSSXXXX
|
||||||
|
BBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
|
||||||
|
XXXX gettext(u'Objects') XXXXX
|
||||||
|
BBB BBBBBBBBBBBBBBBB BB BBBBBBBBBBBBBBBBB
|
||||||
|
XXXXFFFFFFFFFFFFFFXXXXX
|
||||||
|
BBBBBB
|
||||||
|
XXXXX XXXXXXXXX XXXXXXXXXXXXXXBBBBBBBBBB
|
||||||
|
XXXXX
|
||||||
|
BBB BBB BB BBBBBBBB
|
||||||
|
XXXXXX XXXXXXXXXXXXX XXXXXXX XXXXXXXFFFFFFFFFFX XX
|
||||||
|
BBBBBB
|
||||||
|
XXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX
|
||||||
|
XXXXXX XXXXXXXXXXXXX XXXXXXXXXXX XXXXXXXXXXX XX
|
||||||
|
XXXXXX XXXXXXXXXXXXX XXXXXXX gettext(u"Yes, I'm sure") X XX
|
||||||
|
XX XXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX XXXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXX gettext(u'No, take me back') XXXX
|
||||||
|
XXXXXX
|
||||||
|
XXXXXXX
|
||||||
|
BBBBB
|
||||||
|
BBBBBBBB
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
BBBBBBB BBBBBBBBBBBBBBBBBBBBBB
|
||||||
|
BBBB BBBB BBBB BBBBBBBBBB
|
||||||
|
|
||||||
|
BBBBB BBBBBBBBB XXXX XXXXXX XXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXBBBBBBBB
|
||||||
|
|
||||||
|
BBBBB BBBBBBBBBBB
|
||||||
|
XXXX XXXXXXXXXXXXXXXXXXXX
|
||||||
|
XX XXXXXXBBB BBBBBBBBBBBBBXX gettext(u'Home') XXXX
|
||||||
|
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBXXXXXX
|
||||||
|
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXFFFFFFFFXXXX
|
||||||
|
XXXXXXXX BB BBBBBBB gettext(u'Disable %(objects_name)s') SSSSSSS SSSSSSSSSSSSSSSSBBBB gettext(u'Enable %(objects_name)s') SSSSSS SSSSSSSSSSSSSSSSBBBBB
|
||||||
|
XXXXXX
|
||||||
|
BBBBBBBB
|
||||||
|
|
||||||
|
BBBBB BBBBBBB
|
||||||
|
BB BBBBBBBXXX gettext(u'Are you sure you want to disable selected %(objects_name)s?') SSS SSS SSSS SSS SSSS SS SSSSSSS SSSSSSSS SSSSSSSSSSSSSSSSSXXXX
|
||||||
|
BBBBXXX gettext(u'Are you sure you want to enable selected %(objects_name)s?') SSS SSS SSSS SSS SSSS SS SSSSSS SSSSSSSS SSSSSSSSSSSSSSSSSXXXX
|
||||||
|
BBBBB
|
||||||
|
XXXX gettext(u'Objects') XXXXX
|
||||||
|
BBB BBBBBBBBBBBBBBBB BB BBBBBBBBBBBBBBBBB
|
||||||
|
XXXXFFFFFFFFFFFFFFXXXXX
|
||||||
|
BBBBBB
|
||||||
|
XXXXX XXXXXXXXX XXXXXXXXXXXXXXBBBBBBBBBB
|
||||||
|
XXXXX
|
||||||
|
BBB BBB BB BBBBBBBB
|
||||||
|
XXXXXX XXXXXXXXXXXXX XXXXXXX XXXXXXXFFFFFFFFFFX XX
|
||||||
|
BBBBBB
|
||||||
|
XXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXX XXXXXXXX XX
|
||||||
|
XXXXXX XXXXXXXXXXXXX XXXXXXXXXXX XXXXXXXXXXX XX
|
||||||
|
XXXXXX XXXXXXXXXXXXX XXXXXXX gettext(u"Yes, I'm sure") X XX
|
||||||
|
XX XXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX XXXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXX gettext(u'No, take me back') XXXX
|
||||||
|
XXXXXX
|
||||||
|
XXXXXXX
|
||||||
|
BBBBBBBB
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
BBBBBBB BBBBBBBBBBBBBBBBBBBBBBBB
|
||||||
|
BBBB BBBB BBBBBBBBBB
|
||||||
|
|
||||||
|
|
||||||
|
BBBBB BBBBBBBBBBB
|
||||||
|
XXXX XXXXXXXXXXXXXXXXXXXX
|
||||||
|
XX XXXXXXBBB BBBBBBBBBBBBBXX gettext(u'Home') XXXX
|
||||||
|
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBXXXXXX
|
||||||
|
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXFFFFFFFFXXXX
|
||||||
|
XXXXXXXX gettext(u'Select %(name)s account') SSSSSS SSSSSSSS SSSSSSS
|
||||||
|
XXXXXX
|
||||||
|
BBBBBBBB
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
BBBB BBBB BBBBBBBBBB BBBBB
|
||||||
|
XXXXXX
|
||||||
|
XXXXXX
|
||||||
|
XXXXXXXBBBBB BBBBBXXXXXXX XXXXXXX XXXXXXBBBBBBBBXXXXXXXX
|
||||||
|
XXXXX XXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
|
||||||
|
BBBBB BBBBBBBBBBBB
|
||||||
|
XXXXXX XXXXXXXXXXXXXXXX
|
||||||
|
XXXX X
|
||||||
|
XXXXXXXXXX XXXXXX
|
||||||
|
XXXXXXX XX XXXX XXXXXXXXXXX
|
||||||
|
XXXXXX XXXX XXXXXXXXXXX
|
||||||
|
XXXXXXXXXXXX XXXXXX XXXXXXXXXXX XXXXXX XXXXXXX XXXXXX XXXXXXXXXXX
|
||||||
|
XXXXXXXXXX XXXXX
|
||||||
|
XXXXXX XXXXX
|
||||||
|
X
|
||||||
|
XXXXX X
|
||||||
|
XXXXXX XXXXXX
|
||||||
|
XXXXXX XXXXXXXX XXXX XXXXX
|
||||||
|
X
|
||||||
|
XXXXXXXXXXXXXXXX X
|
||||||
|
XXXXXXX XXX XXX XXXX XXXXX
|
||||||
|
X
|
||||||
|
XXXXXXXXXXX X
|
||||||
|
XXXXXXXXXXXXXXXX XXXXX
|
||||||
|
XXXXXXXXXXXX XXXXX
|
||||||
|
XXXXXX XXXXX
|
||||||
|
X
|
||||||
|
XXXXXXXXX X
|
||||||
|
XXXXXXXX XXXX
|
||||||
|
XXXXXXX XXX XXX XXXX XXXXX
|
||||||
|
X
|
||||||
|
XXXXXXXX X
|
||||||
|
XXXXXXXXXXX XXXXX
|
||||||
|
X
|
||||||
|
XX X
|
||||||
|
XXXXXXXXXXX XXXXX
|
||||||
|
X
|
||||||
|
X X
|
||||||
|
XXXXXXXXXXXXXXXX XXXXX
|
||||||
|
XXXXXX XXXXXXX XXXX XXXXX
|
||||||
|
X
|
||||||
|
XXXXXXXX
|
||||||
|
XXXXXXX
|
||||||
|
|
||||||
|
XXXXXX
|
||||||
|
XXXX XXXXXXXXXX gettext(u'Service report generated on') FFFFXXXXXX
|
||||||
|
BBB BBBBBBBB BBBBB BB BBBBBBBB
|
||||||
|
XXXX X XX XXXXXXFFFFFFFFFXXXXXXXXXXX
|
||||||
|
XXXX
|
||||||
|
XXXX XXXXXXXXXXXXXXXXXXXXXXXX
|
||||||
|
gettext(u'account registered on') FFFFXXXX
|
||||||
|
XXX XXXXXXXXXXXXXXXXX
|
||||||
|
XXX XXXXXXXXXXXXXXXXXXX gettext(u'Resources') XXXXX
|
||||||
|
BB BBBBBBBBBBBBBBBBB
|
||||||
|
XXXX
|
||||||
|
BBB BBBBBBBB BB BBBBBBBBBBBBBBBBB
|
||||||
|
XXXXXX XXXXXXFFFFFFFFFXX BB BBBBBBBBBBBBB BB BBBBXXXXX XXXXXXX gettext(u'Used') XXXXXXXXXBBBBBBB BBBBBBBBBBBBBBBBBB BB BBBBBB BBBBBBBBBBBBB BB BBBB X BBBBBXXXXX XXXXXXX gettext(u'Allocated') XXXXXXXXXBBBBBXXXX XXXXX
|
||||||
|
BBBBBB
|
||||||
|
XXXXX
|
||||||
|
BBBBB
|
||||||
|
|
||||||
|
BBB BBBBB BBBBBBB BB BBBBB
|
||||||
|
XXX XXXXXXXXXXXXXXXXXXXXX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXXXXXXXXXXXXXFFFFFFFFXXXXXXXXX
|
||||||
|
XXXX
|
||||||
|
BBB BBB BB BBBBBBB
|
||||||
|
XXX XXXXXXXXXXXXXXXXXX XXXXXXFFFFFFFFFXXXXXX
|
||||||
|
BB BBB BBBBBBBBBBBB X gettext(u'disabled') XBBBBB
|
||||||
|
FFFFFFFF
|
||||||
|
BB BBBBBBBBBBBBB
|
||||||
|
XXXX
|
||||||
|
BBB BBBBBBBB BB BBBBBBBBBBBBB
|
||||||
|
XXXXXX XXXXXXFFFFFFFFFXX BB BBBBBBBBBBBBB BB BBBBXXXXX XXXXXXX gettext(u'Used') XXXXXXXXXBBBBBBB BBBBBBBBBBBBBBBBBB BB BBBBBB BBBBBBBBBBBBB BB BBBB X BBBBBXXXXX XXXXXXX gettext(u'Allocated') XXXXXXXXXBBBBBXXXX XXXXX
|
||||||
|
BBBBBB
|
||||||
|
XXXXX
|
||||||
|
BBBBB
|
||||||
|
XXXXX
|
||||||
|
BBBBBB
|
||||||
|
XXXXX
|
||||||
|
BBBBBB
|
||||||
|
XXXXX
|
||||||
|
XXXXXX
|
||||||
|
BBBBBB
|
||||||
|
XXXXXXX
|
||||||
|
XXXXXXX
|
|
@ -0,0 +1 @@
|
||||||
|
default_app_config = 'orchestra.contrib.bills.apps.BillsConfig'
|
|
@ -68,9 +68,6 @@ class BillLineInline(admin.TabularInline):
|
||||||
|
|
||||||
order_link = admin_link('order', display='pk')
|
order_link = admin_link('order', display='pk')
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("Total")
|
|
||||||
)
|
|
||||||
@mark_safe
|
@mark_safe
|
||||||
def display_total(self, line):
|
def display_total(self, line):
|
||||||
if line.pk:
|
if line.pk:
|
||||||
|
@ -82,6 +79,7 @@ class BillLineInline(admin.TabularInline):
|
||||||
img = static('admin/img/icon-alert.svg')
|
img = static('admin/img/icon-alert.svg')
|
||||||
return '<a href="%s" title="%s">%s <img src="%s"></img></a>' % (url, content, total, img)
|
return '<a href="%s" title="%s">%s <img src="%s"></img></a>' % (url, content, total, img)
|
||||||
return '<a href="%s">%s</a>' % (url, total)
|
return '<a href="%s">%s</a>' % (url, total)
|
||||||
|
display_total.short_description = _("Total")
|
||||||
|
|
||||||
def formfield_for_dbfield(self, db_field, **kwargs):
|
def formfield_for_dbfield(self, db_field, **kwargs):
|
||||||
""" Make value input widget bigger """
|
""" Make value input widget bigger """
|
||||||
|
@ -107,38 +105,31 @@ class ClosedBillLineInline(BillLineInline):
|
||||||
readonly_fields = fields
|
readonly_fields = fields
|
||||||
can_delete = False
|
can_delete = False
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("Description")
|
|
||||||
)
|
|
||||||
@mark_safe
|
@mark_safe
|
||||||
def display_description(self, line):
|
def display_description(self, line):
|
||||||
descriptions = [line.description]
|
descriptions = [line.description]
|
||||||
for subline in line.sublines.all():
|
for subline in line.sublines.all():
|
||||||
descriptions.append(' ' * 4 + subline.description)
|
descriptions.append(' ' * 4 + subline.description)
|
||||||
return '<br>'.join(descriptions)
|
return '<br>'.join(descriptions)
|
||||||
|
display_description.short_description = _("Description")
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("Subtotal")
|
|
||||||
)
|
|
||||||
@mark_safe
|
@mark_safe
|
||||||
def display_subtotal(self, line):
|
def display_subtotal(self, line):
|
||||||
subtotals = [' ' + str(line.subtotal)]
|
subtotals = [' ' + str(line.subtotal)]
|
||||||
for subline in line.sublines.all():
|
for subline in line.sublines.all():
|
||||||
subtotals.append(str(subline.total))
|
subtotals.append(str(subline.total))
|
||||||
return '<br>'.join(subtotals)
|
return '<br>'.join(subtotals)
|
||||||
|
display_subtotal.short_description = _("Subtotal")
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("Total")
|
|
||||||
)
|
|
||||||
def display_total(self, line):
|
def display_total(self, line):
|
||||||
if line.pk:
|
if line.pk:
|
||||||
return line.compute_total()
|
return line.compute_total()
|
||||||
|
display_total.short_description = _("Total")
|
||||||
|
|
||||||
def has_add_permission(self, request, obj):
|
def has_add_permission(self, request, obj):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@admin.register(BillLine)
|
|
||||||
class BillLineAdmin(admin.ModelAdmin):
|
class BillLineAdmin(admin.ModelAdmin):
|
||||||
list_display = (
|
list_display = (
|
||||||
'description', 'bill_link', 'display_is_open', 'account_link', 'rate', 'quantity',
|
'description', 'bill_link', 'display_is_open', 'account_link', 'rate', 'quantity',
|
||||||
|
@ -173,27 +164,21 @@ class BillLineAdmin(admin.ModelAdmin):
|
||||||
order_link = admin_link('order')
|
order_link = admin_link('order')
|
||||||
amended_line_link = admin_link('amended_line')
|
amended_line_link = admin_link('amended_line')
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("Is open"),
|
|
||||||
boolean=True,
|
|
||||||
)
|
|
||||||
def display_is_open(self, instance):
|
def display_is_open(self, instance):
|
||||||
return instance.bill.is_open
|
return instance.bill.is_open
|
||||||
|
display_is_open.short_description = _("Is open")
|
||||||
|
display_is_open.boolean = True
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("Sublines"),
|
|
||||||
ordering='subline_total',
|
|
||||||
)
|
|
||||||
def display_sublinetotal(self, instance):
|
def display_sublinetotal(self, instance):
|
||||||
total = instance.subline_total
|
total = instance.subline_total
|
||||||
return total if total is not None else '---'
|
return total if total is not None else '---'
|
||||||
|
display_sublinetotal.short_description = _("Sublines")
|
||||||
|
display_sublinetotal.admin_order_field = 'subline_total'
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("Total"),
|
|
||||||
ordering='computed_total',
|
|
||||||
)
|
|
||||||
def display_total(self, instance):
|
def display_total(self, instance):
|
||||||
return round(instance.computed_total or 0, 2)
|
return round(instance.computed_total or 0, 2)
|
||||||
|
display_total.short_description = _("Total")
|
||||||
|
display_total.admin_order_field = 'computed_total'
|
||||||
|
|
||||||
def get_readonly_fields(self, request, obj=None):
|
def get_readonly_fields(self, request, obj=None):
|
||||||
fields = super().get_readonly_fields(request, obj)
|
fields = super().get_readonly_fields(request, obj)
|
||||||
|
@ -257,10 +242,6 @@ class BillLineManagerAdmin(BillLineAdmin):
|
||||||
|
|
||||||
|
|
||||||
class BillAdminMixin(AccountAdminMixin):
|
class BillAdminMixin(AccountAdminMixin):
|
||||||
@admin.display(
|
|
||||||
description=_("total"),
|
|
||||||
ordering='approx_total',
|
|
||||||
)
|
|
||||||
@mark_safe
|
@mark_safe
|
||||||
def display_total_with_subtotals(self, bill):
|
def display_total_with_subtotals(self, bill):
|
||||||
if bill.pk:
|
if bill.pk:
|
||||||
|
@ -271,10 +252,9 @@ class BillAdminMixin(AccountAdminMixin):
|
||||||
subtotals.append(_("Taxes %s%% VAT %s &%s;") % (tax, subtotal[1], currency))
|
subtotals.append(_("Taxes %s%% VAT %s &%s;") % (tax, subtotal[1], currency))
|
||||||
subtotals = '\n'.join(subtotals)
|
subtotals = '\n'.join(subtotals)
|
||||||
return '<span title="%s">%s &%s;</span>' % (subtotals, bill.compute_total(), currency)
|
return '<span title="%s">%s &%s;</span>' % (subtotals, bill.compute_total(), currency)
|
||||||
|
display_total_with_subtotals.short_description = _("total")
|
||||||
|
display_total_with_subtotals.admin_order_field = 'approx_total'
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("Payment")
|
|
||||||
)
|
|
||||||
@mark_safe
|
@mark_safe
|
||||||
def display_payment_state(self, bill):
|
def display_payment_state(self, bill):
|
||||||
if bill.pk:
|
if bill.pk:
|
||||||
|
@ -297,6 +277,7 @@ class BillAdminMixin(AccountAdminMixin):
|
||||||
color = PAYMENT_STATE_COLORS.get(bill.payment_state, 'grey')
|
color = PAYMENT_STATE_COLORS.get(bill.payment_state, 'grey')
|
||||||
return '<a href="{url}" style="color:{color}" title="{title}">{name}</a>'.format(
|
return '<a href="{url}" style="color:{color}" title="{title}">{name}</a>'.format(
|
||||||
url=url, color=color, name=state, title=title)
|
url=url, color=color, name=state, title=title)
|
||||||
|
display_payment_state.short_description = _("Payment")
|
||||||
|
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
qs = super().get_queryset(request)
|
qs = super().get_queryset(request)
|
||||||
|
@ -330,7 +311,6 @@ class AmendInline(BillAdminMixin, admin.TabularInline):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@admin.register(AbonoInvoice, AmendmentFee, AmendmentInvoice, Bill, Fee, Invoice, ProForma)
|
|
||||||
class BillAdmin(BillAdminMixin, ExtendedModelAdmin):
|
class BillAdmin(BillAdminMixin, ExtendedModelAdmin):
|
||||||
list_display = (
|
list_display = (
|
||||||
'number', 'type_link', 'account_link', 'closed_on_display', 'updated_on_display',
|
'number', 'type_link', 'account_link', 'closed_on_display', 'updated_on_display',
|
||||||
|
@ -389,29 +369,23 @@ class BillAdmin(BillAdminMixin, ExtendedModelAdmin):
|
||||||
# amend_links.short_description = _("Amends")
|
# amend_links.short_description = _("Amends")
|
||||||
# amend_links.allow_tags = True
|
# amend_links.allow_tags = True
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("lines"),
|
|
||||||
ordering='lines__count',
|
|
||||||
)
|
|
||||||
def num_lines(self, bill):
|
def num_lines(self, bill):
|
||||||
return bill.lines__count
|
return bill.lines__count
|
||||||
|
num_lines.admin_order_field = 'lines__count'
|
||||||
|
num_lines.short_description = _("lines")
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("total"),
|
|
||||||
ordering='approx_total',
|
|
||||||
)
|
|
||||||
def display_total(self, bill):
|
def display_total(self, bill):
|
||||||
currency = settings.BILLS_CURRENCY.lower()
|
currency = settings.BILLS_CURRENCY.lower()
|
||||||
return format_html('{} &{};', bill.compute_total(), currency)
|
return format_html('{} &{};', bill.compute_total(), currency)
|
||||||
|
display_total.short_description = _("total")
|
||||||
|
display_total.admin_order_field = 'approx_total'
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("type"),
|
|
||||||
ordering='type',
|
|
||||||
)
|
|
||||||
def type_link(self, bill):
|
def type_link(self, bill):
|
||||||
bill_type = bill.type.lower()
|
bill_type = bill.type.lower()
|
||||||
url = reverse('admin:bills_%s_changelist' % bill_type)
|
url = reverse('admin:bills_%s_changelist' % bill_type)
|
||||||
return format_html('<a href="{}">{}</a>', url, bill.get_type_display())
|
return format_html('<a href="{}">{}</a>', url, bill.get_type_display())
|
||||||
|
type_link.short_description = _("type")
|
||||||
|
type_link.admin_order_field = 'type'
|
||||||
|
|
||||||
def get_urls(self):
|
def get_urls(self):
|
||||||
""" Hook bill lines management URLs on bill admin """
|
""" Hook bill lines management URLs on bill admin """
|
||||||
|
@ -482,6 +456,14 @@ class BillAdmin(BillAdminMixin, ExtendedModelAdmin):
|
||||||
return super().change_view(request, object_id, **kwargs)
|
return super().change_view(request, object_id, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
admin.site.register(Bill, BillAdmin)
|
||||||
|
admin.site.register(Invoice, BillAdmin)
|
||||||
|
admin.site.register(AmendmentInvoice, BillAdmin)
|
||||||
|
admin.site.register(AbonoInvoice, BillAdmin)
|
||||||
|
admin.site.register(Fee, BillAdmin)
|
||||||
|
admin.site.register(AmendmentFee, BillAdmin)
|
||||||
|
admin.site.register(ProForma, BillAdmin)
|
||||||
|
admin.site.register(BillLine, BillLineAdmin)
|
||||||
|
|
||||||
|
|
||||||
class BillContactInline(admin.StackedInline):
|
class BillContactInline(admin.StackedInline):
|
||||||
|
@ -499,12 +481,10 @@ class BillContactInline(admin.StackedInline):
|
||||||
return super().formfield_for_dbfield(db_field, **kwargs)
|
return super().formfield_for_dbfield(db_field, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
boolean=True,
|
|
||||||
ordering='billcontact',
|
|
||||||
)
|
|
||||||
def has_bill_contact(account):
|
def has_bill_contact(account):
|
||||||
return hasattr(account, 'billcontact')
|
return hasattr(account, 'billcontact')
|
||||||
|
has_bill_contact.boolean = True
|
||||||
|
has_bill_contact.admin_order_field = 'billcontact'
|
||||||
|
|
||||||
|
|
||||||
insertattr(AccountAdmin, 'inlines', BillContactInline)
|
insertattr(AccountAdmin, 'inlines', BillContactInline)
|
||||||
|
|
|
@ -18,7 +18,7 @@ class BillViewSet(LogApiMixin, AccountApiMixin, viewsets.ModelViewSet):
|
||||||
@action(detail=True, methods=['get'])
|
@action(detail=True, methods=['get'])
|
||||||
def document(self, request, pk):
|
def document(self, request, pk):
|
||||||
bill = self.get_object()
|
bill = self.get_object()
|
||||||
content_type = request.headers.get('accept')
|
content_type = request.META.get('HTTP_ACCEPT')
|
||||||
if content_type == 'application/pdf':
|
if content_type == 'application/pdf':
|
||||||
pdf = html_to_pdf(bill.html or bill.render())
|
pdf = html_to_pdf(bill.html or bill.render())
|
||||||
return HttpResponse(pdf, content_type='application/pdf')
|
return HttpResponse(pdf, content_type='application/pdf')
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
||||||
|
default_app_config = 'orchestra.contrib.contacts.apps.ContactsConfig'
|
|
@ -13,7 +13,6 @@ from .filters import EmailUsageListFilter
|
||||||
from .models import Contact
|
from .models import Contact
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Contact)
|
|
||||||
class ContactAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
class ContactAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
list_display = (
|
list_display = (
|
||||||
'dispaly_name', 'email', 'phone', 'phone2', 'country', 'account_link'
|
'dispaly_name', 'email', 'phone', 'phone2', 'country', 'account_link'
|
||||||
|
@ -63,12 +62,10 @@ class ContactAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
)
|
)
|
||||||
actions = (SendEmail(), list_accounts)
|
actions = (SendEmail(), list_accounts)
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("Name"),
|
|
||||||
ordering='short_name',
|
|
||||||
)
|
|
||||||
def dispaly_name(self, contact):
|
def dispaly_name(self, contact):
|
||||||
return str(contact)
|
return str(contact)
|
||||||
|
dispaly_name.short_description = _("Name")
|
||||||
|
dispaly_name.admin_order_field = 'short_name'
|
||||||
|
|
||||||
def formfield_for_dbfield(self, db_field, **kwargs):
|
def formfield_for_dbfield(self, db_field, **kwargs):
|
||||||
""" Make value input widget bigger """
|
""" Make value input widget bigger """
|
||||||
|
@ -79,6 +76,7 @@ class ContactAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
return super(ContactAdmin, self).formfield_for_dbfield(db_field, **kwargs)
|
return super(ContactAdmin, self).formfield_for_dbfield(db_field, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
admin.site.register(Contact, ContactAdmin)
|
||||||
|
|
||||||
|
|
||||||
class ContactInline(admin.StackedInline):
|
class ContactInline(admin.StackedInline):
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
||||||
|
default_app_config = 'orchestra.contrib.databases.apps.DatabasesConfig'
|
|
@ -14,14 +14,11 @@ from .filters import HasUserListFilter, HasDatabaseListFilter
|
||||||
from .forms import DatabaseCreationForm, DatabaseUserChangeForm, DatabaseUserCreationForm, DatabaseForm
|
from .forms import DatabaseCreationForm, DatabaseUserChangeForm, DatabaseUserCreationForm, DatabaseForm
|
||||||
from .models import Database, DatabaseUser
|
from .models import Database, DatabaseUser
|
||||||
|
|
||||||
@admin.action(
|
|
||||||
description="Re-save selected objects"
|
|
||||||
)
|
|
||||||
def save_selected(modeladmin, request, queryset):
|
def save_selected(modeladmin, request, queryset):
|
||||||
for selected in queryset:
|
for selected in queryset:
|
||||||
selected.save()
|
selected.save()
|
||||||
|
save_selected.short_description = "Re-save selected objects"
|
||||||
|
|
||||||
@admin.register(Database)
|
|
||||||
class DatabaseAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
class DatabaseAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
list_display = ('name', 'type', 'target_server', 'display_users', 'account_link')
|
list_display = ('name', 'type', 'target_server', 'display_users', 'account_link')
|
||||||
list_filter = ('type', HasUserListFilter)
|
list_filter = ('type', HasUserListFilter)
|
||||||
|
@ -54,10 +51,6 @@ class DatabaseAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
filter_horizontal = ['users']
|
filter_horizontal = ['users']
|
||||||
actions = (list_accounts, save_selected)
|
actions = (list_accounts, save_selected)
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("Users"),
|
|
||||||
ordering='users__username',
|
|
||||||
)
|
|
||||||
@mark_safe
|
@mark_safe
|
||||||
def display_users(self, db):
|
def display_users(self, db):
|
||||||
links = []
|
links = []
|
||||||
|
@ -65,6 +58,8 @@ class DatabaseAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
link = format_html('<a href="{}">{}</a>', change_url(user), user.username)
|
link = format_html('<a href="{}">{}</a>', change_url(user), user.username)
|
||||||
links.append(link)
|
links.append(link)
|
||||||
return '<br>'.join(links)
|
return '<br>'.join(links)
|
||||||
|
display_users.short_description = _("Users")
|
||||||
|
display_users.admin_order_field = 'users__username'
|
||||||
|
|
||||||
def save_model(self, request, obj, form, change):
|
def save_model(self, request, obj, form, change):
|
||||||
super(DatabaseAdmin, self).save_model(request, obj, form, change)
|
super(DatabaseAdmin, self).save_model(request, obj, form, change)
|
||||||
|
@ -82,7 +77,6 @@ class DatabaseAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
obj.users.add(user)
|
obj.users.add(user)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(DatabaseUser)
|
|
||||||
class DatabaseUserAdmin(SelectAccountAdminMixin, ChangePasswordAdminMixin, ExtendedModelAdmin):
|
class DatabaseUserAdmin(SelectAccountAdminMixin, ChangePasswordAdminMixin, ExtendedModelAdmin):
|
||||||
list_display = ('username', 'target_server', 'type', 'display_databases', 'account_link')
|
list_display = ('username', 'target_server', 'type', 'display_databases', 'account_link')
|
||||||
list_filter = ('type', HasDatabaseListFilter)
|
list_filter = ('type', HasDatabaseListFilter)
|
||||||
|
@ -107,10 +101,6 @@ class DatabaseUserAdmin(SelectAccountAdminMixin, ChangePasswordAdminMixin, Exten
|
||||||
list_prefetch_related = ('databases',)
|
list_prefetch_related = ('databases',)
|
||||||
actions = (list_accounts, save_selected)
|
actions = (list_accounts, save_selected)
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("Databases"),
|
|
||||||
ordering='databases__name',
|
|
||||||
)
|
|
||||||
@mark_safe
|
@mark_safe
|
||||||
def display_databases(self, user):
|
def display_databases(self, user):
|
||||||
links = []
|
links = []
|
||||||
|
@ -118,6 +108,8 @@ class DatabaseUserAdmin(SelectAccountAdminMixin, ChangePasswordAdminMixin, Exten
|
||||||
link = format_html('<a href="{}">{}</a>', change_url(db), db.name)
|
link = format_html('<a href="{}">{}</a>', change_url(db), db.name)
|
||||||
links.append(link)
|
links.append(link)
|
||||||
return '<br>'.join(links)
|
return '<br>'.join(links)
|
||||||
|
display_databases.short_description = _("Databases")
|
||||||
|
display_databases.admin_order_field = 'databases__name'
|
||||||
|
|
||||||
def get_urls(self):
|
def get_urls(self):
|
||||||
useradmin = UserAdmin(DatabaseUser, self.admin_site)
|
useradmin = UserAdmin(DatabaseUser, self.admin_site)
|
||||||
|
@ -133,3 +125,5 @@ class DatabaseUserAdmin(SelectAccountAdminMixin, ChangePasswordAdminMixin, Exten
|
||||||
super(DatabaseUserAdmin, self).save_model(request, obj, form, change)
|
super(DatabaseUserAdmin, self).save_model(request, obj, form, change)
|
||||||
|
|
||||||
|
|
||||||
|
admin.site.register(Database, DatabaseAdmin)
|
||||||
|
admin.site.register(DatabaseUser, DatabaseUserAdmin)
|
||||||
|
|
|
@ -29,6 +29,9 @@ class MySQLController(ServiceController):
|
||||||
# Create database and re-set permissions
|
# Create database and re-set permissions
|
||||||
mysql -e 'CREATE DATABASE `%(database)s`;' || true
|
mysql -e 'CREATE DATABASE `%(database)s`;' || true
|
||||||
mysql mysql -e 'DELETE FROM db WHERE db = "%(database)s";'\
|
mysql mysql -e 'DELETE FROM db WHERE db = "%(database)s";'\
|
||||||
|
|
||||||
|
# wait to create user
|
||||||
|
sleep 1.5
|
||||||
""") % context
|
""") % context
|
||||||
)
|
)
|
||||||
for user in database.users.all():
|
for user in database.users.all():
|
||||||
|
@ -178,7 +181,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('-', '@002d'),
|
'db_dirname': db.name.replace('-', '@002d').replace('.', '@002e'),
|
||||||
'db_id': db.pk,
|
'db_id': db.pk,
|
||||||
'db_type': db.type,
|
'db_type': db.type,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
# Generated by Django 2.2.28 on 2023-06-28 17:06
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.5 on 2021-04-22 11:25
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -8,39 +10,69 @@ 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(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'), ('postgres', 'PostgreSQL')], default='mysql', max_length=32, verbose_name='type')),
|
||||||
|
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='databases', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
|
||||||
|
],
|
||||||
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='DatabaseUser',
|
name='DatabaseUser',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('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')),
|
('username', models.CharField(max_length=16, validators=[orchestra.core.validators.validate_name], verbose_name='username')),
|
||||||
('password', models.CharField(max_length=256, verbose_name='password')),
|
('password', models.CharField(max_length=256, verbose_name='password')),
|
||||||
('type', models.CharField(choices=[('mysql', 'MySQL')], default='mysql', max_length=32, verbose_name='type')),
|
('type', models.CharField(choices=[('mysql', 'MySQL'), ('postgres', 'PostgreSQL')], 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')),
|
('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.CreateModel(
|
migrations.AddField(
|
||||||
name='Database',
|
model_name='database',
|
||||||
fields=[
|
name='users',
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
field=models.ManyToManyField(blank=True, related_name='databases', to='databases.DatabaseUser', verbose_name='users'),
|
||||||
('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')),
|
migrations.AlterUniqueTogether(
|
||||||
('comments', models.TextField(blank=True, default='')),
|
name='databaseuser',
|
||||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='databases', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
|
unique_together=set([('username', 'type')]),
|
||||||
('users', models.ManyToManyField(blank=True, related_name='databases', to='databases.DatabaseUser', verbose_name='users')),
|
),
|
||||||
],
|
migrations.AlterUniqueTogether(
|
||||||
options={
|
name='database',
|
||||||
'unique_together': {('name', 'type')},
|
unique_together=set([('name', 'type')]),
|
||||||
},
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='database',
|
||||||
|
name='type',
|
||||||
|
field=models.CharField(choices=[('mysql', 'MySQL')], default='mysql', max_length=32, verbose_name='type'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='databaseuser',
|
||||||
|
name='type',
|
||||||
|
field=models.CharField(choices=[('mysql', 'MySQL')], default='mysql', max_length=32, verbose_name='type'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='database',
|
||||||
|
name='comments',
|
||||||
|
field=models.TextField(blank=True, default=''),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='database',
|
||||||
|
name='type',
|
||||||
|
field=models.CharField(choices=[('mysql', 'MySQL'), ('postgres', 'PostgreSQL')], default='mysql', max_length=32, verbose_name='type'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='databaseuser',
|
||||||
|
name='type',
|
||||||
|
field=models.CharField(choices=[('mysql', 'MySQL'), ('postgres', 'PostgreSQL')], default='mysql', max_length=32, verbose_name='type'),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,82 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.10.5 on 2021-04-22 11:25
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
import orchestra.core.validators
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
replaces = [('databases', '0001_initial'), ('databases', '0002_auto_20170528_2005'), ('databases', '0003_database_comments'), ('databases', '0004_auto_20210330_1049')]
|
|
||||||
|
|
||||||
initial = True
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
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'), ('postgres', 'PostgreSQL')], default='mysql', max_length=32, verbose_name='type')),
|
|
||||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='databases', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='DatabaseUser',
|
|
||||||
fields=[
|
|
||||||
('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'), ('postgres', 'PostgreSQL')], 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',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='database',
|
|
||||||
name='users',
|
|
||||||
field=models.ManyToManyField(blank=True, related_name='databases', to='databases.DatabaseUser', verbose_name='users'),
|
|
||||||
),
|
|
||||||
migrations.AlterUniqueTogether(
|
|
||||||
name='databaseuser',
|
|
||||||
unique_together=set([('username', 'type')]),
|
|
||||||
),
|
|
||||||
migrations.AlterUniqueTogether(
|
|
||||||
name='database',
|
|
||||||
unique_together=set([('name', 'type')]),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='database',
|
|
||||||
name='type',
|
|
||||||
field=models.CharField(choices=[('mysql', 'MySQL')], default='mysql', max_length=32, verbose_name='type'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='databaseuser',
|
|
||||||
name='type',
|
|
||||||
field=models.CharField(choices=[('mysql', 'MySQL')], default='mysql', max_length=32, verbose_name='type'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='database',
|
|
||||||
name='comments',
|
|
||||||
field=models.TextField(blank=True, default=''),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='database',
|
|
||||||
name='type',
|
|
||||||
field=models.CharField(choices=[('mysql', 'MySQL'), ('postgres', 'PostgreSQL')], default='mysql', max_length=32, verbose_name='type'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='databaseuser',
|
|
||||||
name='type',
|
|
||||||
field=models.CharField(choices=[('mysql', 'MySQL'), ('postgres', 'PostgreSQL')], default='mysql', max_length=32, verbose_name='type'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,20 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.10.5 on 2020-02-04 11:21
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('databases', '0002_auto_20170528_2005'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='database',
|
|
||||||
name='comments',
|
|
||||||
field=models.TextField(default=''),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,30 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.10.5 on 2021-03-30 10:49
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('databases', '0003_database_comments'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='database',
|
|
||||||
name='comments',
|
|
||||||
field=models.TextField(blank=True, default=''),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='database',
|
|
||||||
name='type',
|
|
||||||
field=models.CharField(choices=[('mysql', 'MySQL'), ('postgres', 'PostgreSQL')], default='mysql', max_length=32, verbose_name='type'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='databaseuser',
|
|
||||||
name='type',
|
|
||||||
field=models.CharField(choices=[('mysql', 'MySQL'), ('postgres', 'PostgreSQL')], default='mysql', max_length=32, verbose_name='type'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,6 +1,4 @@
|
||||||
# -*- coding: utf-8 -*-
|
# Generated by Django 2.2.24 on 2024-07-11 12:25
|
||||||
# Generated by Django 1.10.5 on 2017-05-28 18:05
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
@ -8,7 +6,7 @@ from django.db import migrations, models
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('databases', '0001_initial'),
|
('databases', '0006_auto_20230705_1237'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
|
@ -0,0 +1 @@
|
||||||
|
default_app_config = 'orchestra.contrib.domains.apps.DomainsConfig'
|
|
@ -39,11 +39,9 @@ class DomainInline(admin.TabularInline):
|
||||||
domain_link.short_description = _("Name")
|
domain_link.short_description = _("Name")
|
||||||
account_link = admin_link('account')
|
account_link = admin_link('account')
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("Declared records")
|
|
||||||
)
|
|
||||||
def display_records(self, domain):
|
def display_records(self, domain):
|
||||||
return ', '.join([record.type for record in domain.records.all()])
|
return ', '.join([record.type for record in domain.records.all()])
|
||||||
|
display_records.short_description = _("Declared records")
|
||||||
|
|
||||||
def has_add_permission(self, *args, **kwargs):
|
def has_add_permission(self, *args, **kwargs):
|
||||||
return False
|
return False
|
||||||
|
@ -54,7 +52,6 @@ class DomainInline(admin.TabularInline):
|
||||||
return qs.select_related('account').prefetch_related('records')
|
return qs.select_related('account').prefetch_related('records')
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Domain)
|
|
||||||
class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
list_display = (
|
list_display = (
|
||||||
'structured_name', 'display_is_top', 'display_websites', 'display_addresses', 'account_link'
|
'structured_name', 'display_is_top', 'display_websites', 'display_addresses', 'account_link'
|
||||||
|
@ -74,27 +71,19 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
|
|
||||||
top_link = admin_link('top')
|
top_link = admin_link('top')
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("name"),
|
|
||||||
ordering='structured_name',
|
|
||||||
)
|
|
||||||
def structured_name(self, domain):
|
def structured_name(self, domain):
|
||||||
if domain.is_top:
|
if domain.is_top:
|
||||||
return domain.name
|
return domain.name
|
||||||
return mark_safe(' '*4 + domain.name)
|
return mark_safe(' '*4 + domain.name)
|
||||||
|
structured_name.short_description = _("name")
|
||||||
|
structured_name.admin_order_field = 'structured_name'
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("Is top"),
|
|
||||||
boolean=True,
|
|
||||||
ordering='top',
|
|
||||||
)
|
|
||||||
def display_is_top(self, domain):
|
def display_is_top(self, domain):
|
||||||
return domain.is_top
|
return domain.is_top
|
||||||
|
display_is_top.short_description = _("Is top")
|
||||||
|
display_is_top.boolean = True
|
||||||
|
display_is_top.admin_order_field = 'top'
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("Websites"),
|
|
||||||
ordering='websites__name',
|
|
||||||
)
|
|
||||||
@mark_safe
|
@mark_safe
|
||||||
def display_websites(self, domain):
|
def display_websites(self, domain):
|
||||||
if apps.isinstalled('orchestra.contrib.websites'):
|
if apps.isinstalled('orchestra.contrib.websites'):
|
||||||
|
@ -117,11 +106,9 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
)
|
)
|
||||||
return _("No website %s") % (add_link)
|
return _("No website %s") % (add_link)
|
||||||
return '---'
|
return '---'
|
||||||
|
display_websites.admin_order_field = 'websites__name'
|
||||||
|
display_websites.short_description = _("Websites")
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("Addresses"),
|
|
||||||
ordering='addresses__count',
|
|
||||||
)
|
|
||||||
@mark_safe
|
@mark_safe
|
||||||
def display_addresses(self, domain):
|
def display_addresses(self, domain):
|
||||||
if apps.isinstalled('orchestra.contrib.mailboxes'):
|
if apps.isinstalled('orchestra.contrib.mailboxes'):
|
||||||
|
@ -139,10 +126,9 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
return '<a href="%s" title="%s">%s</a> %s' % (url, title, len(addresses), add_link)
|
return '<a href="%s" title="%s">%s</a> %s' % (url, title, len(addresses), add_link)
|
||||||
return _("No address %s") % (add_link)
|
return _("No address %s") % (add_link)
|
||||||
return '---'
|
return '---'
|
||||||
|
display_addresses.short_description = _("Addresses")
|
||||||
|
display_addresses.admin_order_field = 'addresses__count'
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("Implicit records")
|
|
||||||
)
|
|
||||||
@mark_safe
|
@mark_safe
|
||||||
def implicit_records(self, domain):
|
def implicit_records(self, domain):
|
||||||
types = set(domain.records.values_list('type', flat=True))
|
types = set(domain.records.values_list('type', flat=True))
|
||||||
|
@ -162,6 +148,7 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
else:
|
else:
|
||||||
lines.append(line)
|
lines.append(line)
|
||||||
return '<br>'.join(lines)
|
return '<br>'.join(lines)
|
||||||
|
implicit_records.short_description = _("Implicit records")
|
||||||
|
|
||||||
def get_fieldsets(self, request, obj=None):
|
def get_fieldsets(self, request, obj=None):
|
||||||
""" Add SOA fields when domain is top """
|
""" Add SOA fields when domain is top """
|
||||||
|
@ -237,3 +224,4 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
self.save_formset(request, form, formset, change)
|
self.save_formset(request, form, formset, change)
|
||||||
|
|
||||||
|
|
||||||
|
admin.site.register(Domain, DomainAdmin)
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,462 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-06 07:58+0000\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
#: actions.py:25
|
||||||
|
#, python-format
|
||||||
|
msgid "%s zone content"
|
||||||
|
msgstr "%s contingut zona"
|
||||||
|
|
||||||
|
#: actions.py:29 templates/admin/domains/domain/change_form.html:7
|
||||||
|
#: templates/admin/domains/domain/view_zone.html:12
|
||||||
|
msgid "View zone"
|
||||||
|
msgstr "Veure zona"
|
||||||
|
|
||||||
|
#: actions.py:53
|
||||||
|
msgid ""
|
||||||
|
"This subdomain was not explicitly selected but has been automatically added "
|
||||||
|
"to this list."
|
||||||
|
msgstr ""
|
||||||
|
"Aquest subdomini no va ser seleccionat explícitament, però s'ha afegit automàticament"
|
||||||
|
"A aquesta llista."
|
||||||
|
|
||||||
|
|
||||||
|
#: actions.py:88
|
||||||
|
msgid "Records for one selected domain have been updated."
|
||||||
|
msgstr "S'han actualitzat els registres d'un domini seleccionat."
|
||||||
|
|
||||||
|
#: actions.py:89
|
||||||
|
#, python-format
|
||||||
|
msgid "Records for %i selected domains have been updated."
|
||||||
|
msgstr "S'han actualitzat els registres dels dominis seleccionars %i "
|
||||||
|
|
||||||
|
#: actions.py:96 actions.py:97
|
||||||
|
msgid "Edit records"
|
||||||
|
msgstr "Editar registres"
|
||||||
|
|
||||||
|
#: actions.py:112
|
||||||
|
msgid "Set SOA on subdomains is not possible."
|
||||||
|
msgstr "Configurar SOA en subdominis no és possible."
|
||||||
|
|
||||||
|
#: actions.py:120
|
||||||
|
#, python-format
|
||||||
|
msgid "SOA set %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: actions.py:131
|
||||||
|
msgid "SOA record for one domain has been updated."
|
||||||
|
msgstr "El registre SOA per a un domini s'ha actualitzat."
|
||||||
|
|
||||||
|
#: actions.py:132
|
||||||
|
#, python-format
|
||||||
|
msgid "SOA record for %s domains has been updated."
|
||||||
|
msgstr "S'ha actualitzat el rècord SOA per als dominis de %s"
|
||||||
|
|
||||||
|
#: actions.py:139 actions.py:152
|
||||||
|
msgid "Set SOA for selected domains"
|
||||||
|
msgstr "Configurar SOA pels dominis seleccionats"
|
||||||
|
|
||||||
|
#: actions.py:141
|
||||||
|
msgid "Set SOA"
|
||||||
|
msgstr "Afegir SOA"
|
||||||
|
|
||||||
|
#: admin.py:28
|
||||||
|
msgid "Extra records"
|
||||||
|
msgstr "Registres Extra"
|
||||||
|
|
||||||
|
#: admin.py:36
|
||||||
|
msgid "Subdomains"
|
||||||
|
msgstr "Subdominis"
|
||||||
|
|
||||||
|
#: admin.py:39
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Nom"
|
||||||
|
|
||||||
|
#: admin.py:44
|
||||||
|
msgid "Declared records"
|
||||||
|
msgstr "Registres declarats"
|
||||||
|
|
||||||
|
#: admin.py:78 models.py:27
|
||||||
|
msgid "name"
|
||||||
|
msgstr "nom"
|
||||||
|
|
||||||
|
#: admin.py:83
|
||||||
|
msgid "Is top"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin.py:96
|
||||||
|
msgid "Edit website"
|
||||||
|
msgstr "Editar website"
|
||||||
|
|
||||||
|
#: admin.py:105
|
||||||
|
msgid "Add website"
|
||||||
|
msgstr "Crear website"
|
||||||
|
|
||||||
|
#: admin.py:107
|
||||||
|
#, python-format
|
||||||
|
msgid "No website %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin.py:110
|
||||||
|
msgid "Websites"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin.py:119
|
||||||
|
msgid "Add address"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin.py:127
|
||||||
|
#, python-format
|
||||||
|
msgid "No address %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin.py:129
|
||||||
|
msgid "Addresses"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin.py:151 admin.py:158
|
||||||
|
msgid "Implicit records"
|
||||||
|
msgstr "Registres implicits"
|
||||||
|
|
||||||
|
#: admin.py:165
|
||||||
|
msgid "SOA"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin.py:168
|
||||||
|
msgid ""
|
||||||
|
"SOA (Start of Authority) records are used to determine how the zone "
|
||||||
|
"propagates to the secondary nameservers."
|
||||||
|
msgstr ""
|
||||||
|
"Els registres SOA (Start of Authority) s'utilitzen per determinar com la zona"
|
||||||
|
"Es propaga als servidors de noms secundaris."
|
||||||
|
|
||||||
|
#: backends.py:22
|
||||||
|
msgid "Bind9 master domain"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: backends.py:184
|
||||||
|
msgid "Bind9 slave domain"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: filters.py:7
|
||||||
|
msgid "top domains"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: filters.py:12
|
||||||
|
msgid "Top domains"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: filters.py:22
|
||||||
|
msgid "has websites"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: filters.py:27
|
||||||
|
msgid "True"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: filters.py:28
|
||||||
|
msgid "False"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: filters.py:41
|
||||||
|
msgid "has addresses"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: forms.py:14
|
||||||
|
msgid "Names"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: forms.py:15
|
||||||
|
msgid ""
|
||||||
|
"Fully qualified domain name per line. All domains will have the provided "
|
||||||
|
"account and records."
|
||||||
|
msgstr ""
|
||||||
|
"Nom de domini completament qualificat per línia. Tots els dominis tindran el subministrament"
|
||||||
|
"Compte i registres."
|
||||||
|
|
||||||
|
#: forms.py:29
|
||||||
|
#, python-format
|
||||||
|
msgid "%s domain name provided multiple times."
|
||||||
|
msgstr "El nom de domini %s es va proporcionar diverses vegades."
|
||||||
|
|
||||||
|
#: forms.py:65
|
||||||
|
msgid "An account should be provided for top domain names."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: forms.py:72
|
||||||
|
msgid "Provided domain names belong to different accounts."
|
||||||
|
msgstr "Els noms de domini pertanyen a diferents comptes"
|
||||||
|
|
||||||
|
#: forms.py:118
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"%s: Hosts can not have underscore character '_', consider providing a SRV, "
|
||||||
|
"CNAME or TXT record."
|
||||||
|
msgstr ""
|
||||||
|
"%s: Els Hosts no poden tenir un caràcter '_', considereu proporcionar un SRV"
|
||||||
|
"Registre CNAME o TXT."
|
||||||
|
|
||||||
|
#: forms.py:142
|
||||||
|
msgid "Clear refresh"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: forms.py:143
|
||||||
|
msgid "Remove custom refresh value for all selected domains."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: forms.py:145
|
||||||
|
msgid "Clear retry"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: forms.py:146
|
||||||
|
msgid "Remove custom retry value for all selected domains."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: forms.py:148
|
||||||
|
msgid "Clear expire"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: forms.py:149
|
||||||
|
msgid "Remove custom expire value for all selected domains."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: forms.py:151
|
||||||
|
msgid "Clear min TTL"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: forms.py:152
|
||||||
|
msgid "Remove custom min TTL value for all selected domains."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:28
|
||||||
|
msgid "Domain or subdomain name."
|
||||||
|
msgstr "nom de Domini o Subdomini"
|
||||||
|
|
||||||
|
#: models.py:33
|
||||||
|
msgid "Account"
|
||||||
|
msgstr "Compte"
|
||||||
|
|
||||||
|
#: models.py:34
|
||||||
|
msgid "Automatically selected for subdomains."
|
||||||
|
msgstr "Seleccionat automàticament per a subdominis."
|
||||||
|
|
||||||
|
#: models.py:36
|
||||||
|
msgid "top domain"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:37
|
||||||
|
msgid "serial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:38
|
||||||
|
msgid "A revision number that changes whenever this domain is updated."
|
||||||
|
msgstr "Un número de revisió que canvia sempre que aquest domini s'actualitzi."
|
||||||
|
|
||||||
|
#: models.py:39
|
||||||
|
msgid "refresh"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:41
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"The time a secondary DNS server waits before querying the primary DNS "
|
||||||
|
"server's SOA record to check for changes. When the refresh time expires, the "
|
||||||
|
"secondary DNS server requests a copy of the current SOA record from the "
|
||||||
|
"primary. The primary DNS server complies with this request. The secondary "
|
||||||
|
"DNS server compares the serial number of the primary DNS server's current "
|
||||||
|
"SOA record and the serial number in it's own SOA record. If they are "
|
||||||
|
"different, the secondary DNS server will request a zone transfer from the "
|
||||||
|
"primary DNS server. The default value is <tt>%s</tt>."
|
||||||
|
msgstr ""
|
||||||
|
"El temps que un servidor DNS secundari espera abans de consultar el DNS primari"
|
||||||
|
"Registre SOA del servidor per comprovar si hi ha canvis. Quan el temps d'actualització caduca,"
|
||||||
|
"El servidor DNS secundari sol·licita una còpia del registre SOA actual del"
|
||||||
|
"Primària. El servidor DNS primari compleix aquesta sol·licitud. La secundària"
|
||||||
|
"El servidor DNS compara el número de sèrie del corrent principal del servidor DNS"
|
||||||
|
"Registre SOA i el número de sèrie del seu propi registre SOA. Si ho són"
|
||||||
|
"Diferent, el servidor DNS secundari sol·licitarà una transferència de zona des del"
|
||||||
|
"Servidor DNS primari. El valor per defecte és <tt>%s</tt>."
|
||||||
|
|
||||||
|
#: models.py:50
|
||||||
|
msgid "retry"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:52
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"The time a secondary server waits before retrying a failed zone transfer. "
|
||||||
|
"Normally, the retry time is less than the refresh time. The default value is "
|
||||||
|
"<tt>%s</tt>."
|
||||||
|
msgstr ""
|
||||||
|
"El temps que un servidor secundari espera abans de tornar a tornar a transferir una zona fallida."
|
||||||
|
"Normalment, el temps de tornada és inferior al temps d'actualització. El valor predeterminat és"
|
||||||
|
"<tt>%s</tt>."
|
||||||
|
|
||||||
|
#: models.py:55
|
||||||
|
msgid "expire"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:57
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"The time that a secondary server will keep trying to complete a zone "
|
||||||
|
"transfer. If this time expires prior to a successful zone transfer, the "
|
||||||
|
"secondary server will expire its zone file. This means the secondary will "
|
||||||
|
"stop answering queries. The default value is <tt>%s</tt>."
|
||||||
|
msgstr ""
|
||||||
|
"El temps que un servidor secundari continuarà intentant completar una zona"
|
||||||
|
"Transferència. Si aquesta vegada caduca abans d'una transferència de zona amb èxit,"
|
||||||
|
"El servidor secundari caducarà el seu fitxer de zona. Això significa que la voluntat secundària"
|
||||||
|
"Deixa de respondre a les consultes. El valor predeterminat és <tt>%s</tt>."
|
||||||
|
|
||||||
|
#: models.py:62
|
||||||
|
msgid "min TTL"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:64
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"The minimum time-to-live value applies to all resource records in the zone "
|
||||||
|
"file. This value is supplied in query responses to inform other servers how "
|
||||||
|
"long they should keep the data in cache. The default value is <tt>%s</tt>."
|
||||||
|
msgstr ""
|
||||||
|
"El valor mínim de temps en viu s'aplica a tots els registres de recursos de la zona"
|
||||||
|
"Fitxer. Aquest valor es subministra a les respostes de consulta per informar a altres servidors com"
|
||||||
|
"Long han de mantenir les dades en memòria cau. El valor predeterminat és <tt>%s</tt>"
|
||||||
|
|
||||||
|
#: models.py:118
|
||||||
|
msgid "top domain with one subdomain"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:119
|
||||||
|
#, python-format
|
||||||
|
msgid "top domain with %d subdomains"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:121
|
||||||
|
msgid "subdomain"
|
||||||
|
msgstr "subdomini"
|
||||||
|
|
||||||
|
#: models.py:308
|
||||||
|
msgid "A (IPv4 address)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:309
|
||||||
|
msgid "AAAA (IPv6 address)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:329
|
||||||
|
msgid "domain"
|
||||||
|
msgstr "domini"
|
||||||
|
|
||||||
|
#: models.py:330
|
||||||
|
msgid "TTL"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:331
|
||||||
|
#, python-format
|
||||||
|
msgid "Record TTL, defaults to %s"
|
||||||
|
msgstr "Registre TTL, per defecte a %s"
|
||||||
|
|
||||||
|
#: models.py:333
|
||||||
|
msgid "type"
|
||||||
|
msgstr "tipus"
|
||||||
|
|
||||||
|
#: models.py:335
|
||||||
|
msgid "value"
|
||||||
|
msgstr "valor"
|
||||||
|
|
||||||
|
#: models.py:336
|
||||||
|
msgid "MX, NS and CNAME records sould end with a dot."
|
||||||
|
msgstr "Els registres de MX, NS i CNAME s'acaben amb un punt."
|
||||||
|
|
||||||
|
#: serializers.py:36
|
||||||
|
msgid "Can not create subdomains of other users domains"
|
||||||
|
msgstr "No es pot crear subdominis d'altres dominis d'usuaris"
|
||||||
|
|
||||||
|
#: templates/admin/domains/domain/change_form.html:11
|
||||||
|
msgid "History"
|
||||||
|
msgstr "Historial"
|
||||||
|
|
||||||
|
#: templates/admin/domains/domain/change_form.html:13
|
||||||
|
msgid "View on site"
|
||||||
|
msgstr "Veure al lloc"
|
||||||
|
|
||||||
|
#: templates/admin/domains/domain/view_zone.html:8
|
||||||
|
msgid "Home"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: validators.py:28
|
||||||
|
msgid "This domain name is not allowed"
|
||||||
|
msgstr "Aquest nom de domini no està permès"
|
||||||
|
|
||||||
|
#: validators.py:37
|
||||||
|
msgid "Not a valid domain name."
|
||||||
|
msgstr "No és un nom de domini vàlid."
|
||||||
|
|
||||||
|
#: validators.py:46
|
||||||
|
#, python-format
|
||||||
|
msgid "%s is not an appropiate zone interval value"
|
||||||
|
msgstr "%s no és un valor d'interval de zona adequat"
|
||||||
|
|
||||||
|
#: validators.py:57
|
||||||
|
msgid ""
|
||||||
|
"Labels must start and end with a letter or digit, and have as interior "
|
||||||
|
"characters only letters, digits, and hyphen."
|
||||||
|
msgstr ""
|
||||||
|
"Les etiquetes han de començar i acabar amb una lletra o dígit i tenir en l'interior"
|
||||||
|
"Només caràcters lletres, dígits i guionet."
|
||||||
|
|
||||||
|
#: validators.py:61
|
||||||
|
msgid "Use a fully expanded domain name ending with a dot."
|
||||||
|
msgstr "Utilitzeu un nom de domini complet amb un punt final."
|
||||||
|
|
||||||
|
#: validators.py:64
|
||||||
|
msgid "Labels must be 63 characters or less."
|
||||||
|
msgstr "Les etiquetes han de tenir 63 caràcters o menys."
|
||||||
|
|
||||||
|
#: validators.py:68
|
||||||
|
msgid ""
|
||||||
|
"MX record format is 'priority domain.' tuple, with priority being a number."
|
||||||
|
msgstr ""
|
||||||
|
"El format de registre MX és 'domini prioritari'. Tuple, amb la prioritat que és un número "
|
||||||
|
|
||||||
|
#: validators.py:83 validators.py:95
|
||||||
|
#, python-format
|
||||||
|
msgid "%s is not an appropiate SRV record value"
|
||||||
|
msgstr "%s no és un valor de registre SRV Apropiat"
|
||||||
|
|
||||||
|
#: validators.py:111
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"%s is not an appropiate CAA record value, sintax: 0-255 issue|issuewild|"
|
||||||
|
"iodef \"domain|mailto:email\""
|
||||||
|
msgstr ""
|
||||||
|
"%s no és un valor de registre CAA adequat, sintaxi: 0-255 issue|issuewild|"
|
||||||
|
"iodef \"domain|mailto:email\""
|
||||||
|
|
||||||
|
#: validators.py:134
|
||||||
|
msgid ""
|
||||||
|
"This record value contains spaces, you must enclose the string in double "
|
||||||
|
"quotes; otherwise, individual words will be separately quoted and break up "
|
||||||
|
"the record into multiple parts."
|
||||||
|
msgstr ""
|
||||||
|
"Aquest valor de registre conté espais, heu d'incloure la cadena ab cometes dobles"
|
||||||
|
"en cas contrari, les paraules individuals es citaran per separat i es trencaran"
|
||||||
|
"El registre en diverses parts"
|
Binary file not shown.
|
@ -0,0 +1,461 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-05 10:11+0000\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
#: actions.py:25
|
||||||
|
#, python-format
|
||||||
|
msgid "%s zone content"
|
||||||
|
msgstr "%s contenido de zona"
|
||||||
|
|
||||||
|
#: actions.py:29 templates/admin/domains/domain/change_form.html:7
|
||||||
|
#: templates/admin/domains/domain/view_zone.html:12
|
||||||
|
msgid "View zone"
|
||||||
|
msgstr "Ver zona"
|
||||||
|
|
||||||
|
#: actions.py:53
|
||||||
|
msgid ""
|
||||||
|
"This subdomain was not explicitly selected but has been automatically added "
|
||||||
|
"to this list."
|
||||||
|
msgstr ""
|
||||||
|
"Este subdominio no fue seleccionado explícitamente, pero se ha agregado automáticamente"
|
||||||
|
"A esta lista"
|
||||||
|
|
||||||
|
#: actions.py:88
|
||||||
|
msgid "Records for one selected domain have been updated."
|
||||||
|
msgstr "Se han actualizado los registros del dominio seleccionado"
|
||||||
|
|
||||||
|
#: actions.py:89
|
||||||
|
#, python-format
|
||||||
|
msgid "Records for %i selected domains have been updated."
|
||||||
|
msgstr "Se han actualizado los registros para los %i dominios seleccionados"
|
||||||
|
|
||||||
|
#: actions.py:96 actions.py:97
|
||||||
|
msgid "Edit records"
|
||||||
|
msgstr "Editar Registros"
|
||||||
|
|
||||||
|
#: actions.py:112
|
||||||
|
msgid "Set SOA on subdomains is not possible."
|
||||||
|
msgstr "No es posible añadir el registro SOA en los subdominios"
|
||||||
|
|
||||||
|
#: actions.py:120
|
||||||
|
#, python-format
|
||||||
|
msgid "SOA set %s"
|
||||||
|
msgstr "Añadir SOA %s"
|
||||||
|
|
||||||
|
#: actions.py:131
|
||||||
|
msgid "SOA record for one domain has been updated."
|
||||||
|
msgstr "Se ha actualizado el registro SOA del dominio"
|
||||||
|
|
||||||
|
#: actions.py:132
|
||||||
|
#, python-format
|
||||||
|
msgid "SOA record for %s domains has been updated."
|
||||||
|
msgstr "Se actualizo el registro SOA para los dominios %s"
|
||||||
|
|
||||||
|
#: actions.py:139 actions.py:152
|
||||||
|
msgid "Set SOA for selected domains"
|
||||||
|
msgstr "Añadir SOA en los dominios seleccionados"
|
||||||
|
|
||||||
|
#: actions.py:141
|
||||||
|
msgid "Set SOA"
|
||||||
|
msgstr "Añadir SOA"
|
||||||
|
|
||||||
|
#: admin.py:28
|
||||||
|
msgid "Extra records"
|
||||||
|
msgstr "Registros extra"
|
||||||
|
|
||||||
|
#: admin.py:36
|
||||||
|
msgid "Subdomains"
|
||||||
|
msgstr "Subdominios"
|
||||||
|
|
||||||
|
#: admin.py:39
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Nombre"
|
||||||
|
|
||||||
|
#: admin.py:44
|
||||||
|
msgid "Declared records"
|
||||||
|
msgstr "Registros declarados"
|
||||||
|
|
||||||
|
#: admin.py:78 models.py:27
|
||||||
|
msgid "name"
|
||||||
|
msgstr "Nombre"
|
||||||
|
|
||||||
|
#: admin.py:83
|
||||||
|
msgid "Is top"
|
||||||
|
msgstr "Es top level"
|
||||||
|
|
||||||
|
#: admin.py:96
|
||||||
|
msgid "Edit website"
|
||||||
|
msgstr "Editar WebSite"
|
||||||
|
|
||||||
|
#: admin.py:105
|
||||||
|
msgid "Add website"
|
||||||
|
msgstr "Añadir WebSite"
|
||||||
|
|
||||||
|
#: admin.py:107
|
||||||
|
#, python-format
|
||||||
|
msgid "No website %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin.py:110
|
||||||
|
msgid "Websites"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin.py:119
|
||||||
|
msgid "Add address"
|
||||||
|
msgstr "Añadir dirección"
|
||||||
|
|
||||||
|
#: admin.py:127
|
||||||
|
#, python-format
|
||||||
|
msgid "No address %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin.py:129
|
||||||
|
msgid "Addresses"
|
||||||
|
msgstr "Direcciones"
|
||||||
|
|
||||||
|
#: admin.py:151 admin.py:158
|
||||||
|
msgid "Implicit records"
|
||||||
|
msgstr "Registros implicitos"
|
||||||
|
|
||||||
|
#: admin.py:165
|
||||||
|
msgid "SOA"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin.py:168
|
||||||
|
msgid ""
|
||||||
|
"SOA (Start of Authority) records are used to determine how the zone "
|
||||||
|
"propagates to the secondary nameservers."
|
||||||
|
msgstr ""
|
||||||
|
"Los registros SOA (inicio de la autoridad) se utilizan para determinar cómo la zona"
|
||||||
|
"Se propaga a los servidores de nombres secundarios"
|
||||||
|
|
||||||
|
#: backends.py:22
|
||||||
|
msgid "Bind9 master domain"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: backends.py:184
|
||||||
|
msgid "Bind9 slave domain"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: filters.py:7
|
||||||
|
msgid "top domains"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: filters.py:12
|
||||||
|
msgid "Top domains"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: filters.py:22
|
||||||
|
msgid "has websites"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: filters.py:27
|
||||||
|
msgid "True"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: filters.py:28
|
||||||
|
msgid "False"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: filters.py:41
|
||||||
|
msgid "has addresses"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: forms.py:14
|
||||||
|
msgid "Names"
|
||||||
|
msgstr "Nombres"
|
||||||
|
|
||||||
|
#: forms.py:15
|
||||||
|
msgid ""
|
||||||
|
"Fully qualified domain name per line. All domains will have the provided "
|
||||||
|
"account and records."
|
||||||
|
msgstr ""
|
||||||
|
"Nombre de dominio totalmente calificado por línea. Todos los dominios tendrán los proporcionados"
|
||||||
|
"Cuenta y registros"
|
||||||
|
|
||||||
|
#: forms.py:29
|
||||||
|
#, python-format
|
||||||
|
msgid "%s domain name provided multiple times."
|
||||||
|
msgstr "%s Nombre de dominio proporcionado varias veces."
|
||||||
|
|
||||||
|
#: forms.py:65
|
||||||
|
msgid "An account should be provided for top domain names."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: forms.py:72
|
||||||
|
msgid "Provided domain names belong to different accounts."
|
||||||
|
msgstr "Los nombres de dominio proporcionados pertenecen a diferentes cuentas"
|
||||||
|
|
||||||
|
#: forms.py:118
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"%s: Hosts can not have underscore character '_', consider providing a SRV, "
|
||||||
|
"CNAME or TXT record."
|
||||||
|
msgstr ""
|
||||||
|
"%s: los hosts no pueden tener un carácter subrayado '_', considere proporcionar un SRV, "
|
||||||
|
"Registro CNAME o TXT."
|
||||||
|
|
||||||
|
#: forms.py:142
|
||||||
|
msgid "Clear refresh"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: forms.py:143
|
||||||
|
msgid "Remove custom refresh value for all selected domains."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: forms.py:145
|
||||||
|
msgid "Clear retry"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: forms.py:146
|
||||||
|
msgid "Remove custom retry value for all selected domains."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: forms.py:148
|
||||||
|
msgid "Clear expire"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: forms.py:149
|
||||||
|
msgid "Remove custom expire value for all selected domains."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: forms.py:151
|
||||||
|
msgid "Clear min TTL"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: forms.py:152
|
||||||
|
msgid "Remove custom min TTL value for all selected domains."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:28
|
||||||
|
msgid "Domain or subdomain name."
|
||||||
|
msgstr "Dominio o Subdominio"
|
||||||
|
|
||||||
|
#: models.py:33
|
||||||
|
msgid "Account"
|
||||||
|
msgstr "Cuenta"
|
||||||
|
|
||||||
|
#: models.py:34
|
||||||
|
msgid "Automatically selected for subdomains."
|
||||||
|
msgstr "Seleccionado automáticamente para subdominios"
|
||||||
|
|
||||||
|
#: models.py:36
|
||||||
|
msgid "top domain"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:37
|
||||||
|
msgid "serial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:38
|
||||||
|
msgid "A revision number that changes whenever this domain is updated."
|
||||||
|
msgstr "Un número de revisión que cambia cada vez que se actualiza este dominio"
|
||||||
|
|
||||||
|
#: models.py:39
|
||||||
|
msgid "refresh"
|
||||||
|
msgstr "actualizar"
|
||||||
|
|
||||||
|
#: models.py:41
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"The time a secondary DNS server waits before querying the primary DNS "
|
||||||
|
"server's SOA record to check for changes. When the refresh time expires, the "
|
||||||
|
"secondary DNS server requests a copy of the current SOA record from the "
|
||||||
|
"primary. The primary DNS server complies with this request. The secondary "
|
||||||
|
"DNS server compares the serial number of the primary DNS server's current "
|
||||||
|
"SOA record and the serial number in it's own SOA record. If they are "
|
||||||
|
"different, the secondary DNS server will request a zone transfer from the "
|
||||||
|
"primary DNS server. The default value is <tt>%s</tt>."
|
||||||
|
msgstr ""
|
||||||
|
"La hora en que un servidor DNS secundario espera antes de consultar el DNS primario"
|
||||||
|
"El registro SOA del servidor para verificar los cambios. Cuando la tiempo de actualización expira,"
|
||||||
|
"El servidor DNS secundario solicita una copia del registro SOA actual del"
|
||||||
|
"Primario. El servidor DNS principal cumple con esta solicitud. El secundario"
|
||||||
|
"El servidor DNS compara el número de serie del servidor DNS principal actual"
|
||||||
|
"SOA Record y el número de serie en su propio registro SOA. Si lo son"
|
||||||
|
"Diferente, el servidor DNS secundario solicitará una transferencia de zona del"
|
||||||
|
"Servidor DNS primario. El valor predeterminado es <tt>%s</tt>"
|
||||||
|
|
||||||
|
#: models.py:50
|
||||||
|
msgid "retry"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:52
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"The time a secondary server waits before retrying a failed zone transfer. "
|
||||||
|
"Normally, the retry time is less than the refresh time. The default value is "
|
||||||
|
"<tt>%s</tt>."
|
||||||
|
msgstr ""
|
||||||
|
"El tiempo en que un servidor secundario espera antes de volver a intentar una transferencia de zona fallida"
|
||||||
|
"Normalmente, el tiempo de reintento es menor que el tiempo de actualización. El valor predeterminado es"
|
||||||
|
"<Tt>%s</tt>"
|
||||||
|
|
||||||
|
#: models.py:55
|
||||||
|
msgid "expire"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:57
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"The time that a secondary server will keep trying to complete a zone "
|
||||||
|
"transfer. If this time expires prior to a successful zone transfer, the "
|
||||||
|
"secondary server will expire its zone file. This means the secondary will "
|
||||||
|
"stop answering queries. The default value is <tt>%s</tt>."
|
||||||
|
msgstr ""
|
||||||
|
"El momento en que un servidor secundario seguirá intentando completar una zona"
|
||||||
|
"Transferencia. Si este tiempo expira antes de una transferencia de zona exitosa,"
|
||||||
|
"El servidor secundario caducará su archivo de zona. Esto significa que el secundario lo hará"
|
||||||
|
"Deje de responder consultas. El valor predeterminado es <tt>%s</tt>"
|
||||||
|
|
||||||
|
#: models.py:62
|
||||||
|
msgid "min TTL"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:64
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"The minimum time-to-live value applies to all resource records in the zone "
|
||||||
|
"file. This value is supplied in query responses to inform other servers how "
|
||||||
|
"long they should keep the data in cache. The default value is <tt>%s</tt>."
|
||||||
|
msgstr ""
|
||||||
|
"El valor mínimo de tiempo de vida se aplica a todos los registros de recursos en la zona"
|
||||||
|
"Archivo. Este valor se suministra en las respuestas de consulta para informar a otros servidores cómo"
|
||||||
|
"Durante mucho tiempo deberían mantener los datos en caché. El valor predeterminado es <tt>%s </tt>"
|
||||||
|
|
||||||
|
#: models.py:118
|
||||||
|
msgid "top domain with one subdomain"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:119
|
||||||
|
#, python-format
|
||||||
|
msgid "top domain with %d subdomains"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:121
|
||||||
|
msgid "subdomain"
|
||||||
|
msgstr "Subdominio"
|
||||||
|
|
||||||
|
#: models.py:308
|
||||||
|
msgid "A (IPv4 address)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:309
|
||||||
|
msgid "AAAA (IPv6 address)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:329
|
||||||
|
msgid "domain"
|
||||||
|
msgstr "dominio"
|
||||||
|
|
||||||
|
#: models.py:330
|
||||||
|
msgid "TTL"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:331
|
||||||
|
#, python-format
|
||||||
|
msgid "Record TTL, defaults to %s"
|
||||||
|
msgstr "Registro TTL, por defecto %s"
|
||||||
|
|
||||||
|
#: models.py:333
|
||||||
|
msgid "type"
|
||||||
|
msgstr "tipo"
|
||||||
|
|
||||||
|
#: models.py:335
|
||||||
|
msgid "value"
|
||||||
|
msgstr "valor"
|
||||||
|
|
||||||
|
#: models.py:336
|
||||||
|
msgid "MX, NS and CNAME records sould end with a dot."
|
||||||
|
msgstr "Los registros MX, NS and CNAME han de acabar con punto"
|
||||||
|
|
||||||
|
#: serializers.py:36
|
||||||
|
msgid "Can not create subdomains of other users domains"
|
||||||
|
msgstr "No puede crear subdominios de los dominios de otros usuarios"
|
||||||
|
|
||||||
|
#: templates/admin/domains/domain/change_form.html:11
|
||||||
|
msgid "History"
|
||||||
|
msgstr "Historial"
|
||||||
|
|
||||||
|
#: templates/admin/domains/domain/change_form.html:13
|
||||||
|
msgid "View on site"
|
||||||
|
msgstr "Ver en el sitio"
|
||||||
|
|
||||||
|
#: templates/admin/domains/domain/view_zone.html:8
|
||||||
|
msgid "Home"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: validators.py:28
|
||||||
|
msgid "This domain name is not allowed"
|
||||||
|
msgstr "Este nombre de dominio no esta permitido"
|
||||||
|
|
||||||
|
#: validators.py:37
|
||||||
|
msgid "Not a valid domain name."
|
||||||
|
msgstr "No es nombre de dominio valido"
|
||||||
|
|
||||||
|
#: validators.py:46
|
||||||
|
#, python-format
|
||||||
|
msgid "%s is not an appropiate zone interval value"
|
||||||
|
msgstr "%s no es un valor de intervalo de zona apropiado"
|
||||||
|
|
||||||
|
#: validators.py:57
|
||||||
|
msgid ""
|
||||||
|
"Labels must start and end with a letter or digit, and have as interior "
|
||||||
|
"characters only letters, digits, and hyphen."
|
||||||
|
msgstr ""
|
||||||
|
"Las etiquetas deben comenzar y terminar con una letra o dígito, y tener en su interior"
|
||||||
|
"Caracteres solo letras, dígitos y guiones"
|
||||||
|
|
||||||
|
#: validators.py:61
|
||||||
|
msgid "Use a fully expanded domain name ending with a dot."
|
||||||
|
msgstr "Use un nombre de dominio completo que termine con un punto"
|
||||||
|
|
||||||
|
#: validators.py:64
|
||||||
|
msgid "Labels must be 63 characters or less."
|
||||||
|
msgstr "Las etiquetas deben ser de 63 caracteres o menos"
|
||||||
|
|
||||||
|
#: validators.py:68
|
||||||
|
msgid ""
|
||||||
|
"MX record format is 'priority domain.' tuple, with priority being a number."
|
||||||
|
msgstr ""
|
||||||
|
"El formato de registro MX es 'dominio prioritario'. Tuple, con la prioridad siendo un número "
|
||||||
|
|
||||||
|
#: validators.py:83 validators.py:95
|
||||||
|
#, python-format
|
||||||
|
msgid "%s is not an appropiate SRV record value"
|
||||||
|
msgstr "%s no es un valor de SRV apropiado"
|
||||||
|
|
||||||
|
#: validators.py:111
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"%s is not an appropiate CAA record value, sintax: 0-255 issue|issuewild|"
|
||||||
|
"iodef \"domain|mailto:email\""
|
||||||
|
msgstr ""
|
||||||
|
"%s no es un valor de registro de CAA apropiado, sintaxis: 0-255 issue|issuewild|"
|
||||||
|
"iodef \"domain|mailto:email\""
|
||||||
|
|
||||||
|
#: validators.py:134
|
||||||
|
msgid ""
|
||||||
|
"This record value contains spaces, you must enclose the string in double "
|
||||||
|
"quotes; otherwise, individual words will be separately quoted and break up "
|
||||||
|
"the record into multiple parts."
|
||||||
|
msgstr ""
|
||||||
|
"Este valor de registro contiene espacios, debe encerrar la cadena en el doble"
|
||||||
|
"Comillas; de lo contrario, las palabras individuales serán citadas por separado y se romperán"
|
||||||
|
"El registro en múltiples partes"
|
|
@ -1,15 +1,17 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.5 on 2021-04-22 11:27
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
import orchestra.contrib.domains.utils
|
import orchestra.contrib.domains.utils
|
||||||
import orchestra.contrib.domains.validators
|
import orchestra.contrib.domains.validators
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
]
|
]
|
||||||
|
@ -18,21 +20,61 @@ class Migration(migrations.Migration):
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Domain',
|
name='Domain',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(serialize=False, primary_key=True, auto_created=True, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('name', models.CharField(unique=True, max_length=256, validators=[orchestra.contrib.domains.validators.validate_domain_name, orchestra.contrib.domains.validators.validate_allowed_domain], verbose_name='name', help_text='Domain or subdomain name.')),
|
('name', models.CharField(help_text='Domain or subdomain name.', max_length=256, unique=True, validators=[orchestra.contrib.domains.validators.validate_domain_name, orchestra.contrib.domains.validators.validate_allowed_domain], verbose_name='name')),
|
||||||
('serial', models.IntegerField(default=orchestra.contrib.domains.utils.generate_zone_serial, verbose_name='serial', help_text='Serial number')),
|
('serial', models.IntegerField(default=orchestra.contrib.domains.utils.generate_zone_serial, help_text='Serial number', verbose_name='serial')),
|
||||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='domains', help_text='Automatically selected for subdomains.', to=settings.AUTH_USER_MODEL, verbose_name='Account', blank=True)),
|
('account', models.ForeignKey(blank=True, help_text='Automatically selected for subdomains.', on_delete=django.db.models.deletion.CASCADE, related_name='domains', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
|
||||||
('top', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, null=True, to='domains.Domain', editable=False, related_name='subdomain_set')),
|
('top', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subdomain_set', to='domains.Domain')),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Record',
|
name='Record',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(serialize=False, primary_key=True, auto_created=True, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('ttl', models.CharField(help_text='Record TTL, defaults to 1h', max_length=8, validators=[orchestra.contrib.domains.validators.validate_zone_interval], verbose_name='TTL', blank=True)),
|
('ttl', models.CharField(blank=True, help_text='Record TTL, defaults to 1h', max_length=8, validators=[orchestra.contrib.domains.validators.validate_zone_interval], verbose_name='TTL')),
|
||||||
('type', models.CharField(max_length=32, verbose_name='type', choices=[('MX', 'MX'), ('NS', 'NS'), ('CNAME', 'CNAME'), ('A', 'A (IPv4 address)'), ('AAAA', 'AAAA (IPv6 address)'), ('SRV', 'SRV'), ('TXT', 'TXT'), ('SOA', 'SOA')])),
|
('type', models.CharField(choices=[('MX', 'MX'), ('NS', 'NS'), ('CNAME', 'CNAME'), ('A', 'A (IPv4 address)'), ('AAAA', 'AAAA (IPv6 address)'), ('SRV', 'SRV'), ('TXT', 'TXT'), ('SPF', 'SPF')], max_length=32, verbose_name='type')),
|
||||||
('value', models.CharField(max_length=256, verbose_name='value')),
|
('value', models.CharField(help_text='MX, NS and CNAME records sould end with a dot.', max_length=1024, verbose_name='value')),
|
||||||
('domain', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='records', to='domains.Domain', verbose_name='domain')),
|
('domain', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='records', to='domains.Domain', verbose_name='domain')),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='domain',
|
||||||
|
name='serial',
|
||||||
|
field=models.IntegerField(default=orchestra.contrib.domains.utils.generate_zone_serial, editable=False, help_text='A revision number that changes whenever this domain is updated.', verbose_name='serial'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='domain',
|
||||||
|
name='expire',
|
||||||
|
field=models.CharField(blank=True, help_text='The time that a secondary server will keep trying to complete a zone transfer. If this time expires prior to a successful zone transfer, the secondary server will expire its zone file. This means the secondary will stop answering queries. The default value is <tt>4w</tt>.', max_length=16, validators=[orchestra.contrib.domains.validators.validate_zone_interval], verbose_name='expire'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='domain',
|
||||||
|
name='min_ttl',
|
||||||
|
field=models.CharField(blank=True, help_text='The minimum time-to-live value applies to all resource records in the zone file. This value is supplied in query responses to inform other servers how long they should keep the data in cache. The default value is <tt>1h</tt>.', max_length=16, validators=[orchestra.contrib.domains.validators.validate_zone_interval], verbose_name='min TTL'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='domain',
|
||||||
|
name='refresh',
|
||||||
|
field=models.CharField(blank=True, help_text="The time a secondary DNS server waits before querying the primary DNS server's SOA record to check for changes. When the refresh time expires, the secondary DNS server requests a copy of the current SOA record from the primary. The primary DNS server complies with this request. The secondary DNS server compares the serial number of the primary DNS server's current SOA record and the serial number in it's own SOA record. If they are different, the secondary DNS server will request a zone transfer from the primary DNS server. The default value is <tt>1d</tt>.", max_length=16, validators=[orchestra.contrib.domains.validators.validate_zone_interval], verbose_name='refresh'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='domain',
|
||||||
|
name='retry',
|
||||||
|
field=models.CharField(blank=True, help_text='The time a secondary server waits before retrying a failed zone transfer. Normally, the retry time is less than the refresh time. The default value is <tt>2h</tt>.', max_length=16, validators=[orchestra.contrib.domains.validators.validate_zone_interval], verbose_name='retry'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='domain',
|
||||||
|
name='name',
|
||||||
|
field=models.CharField(db_index=True, help_text='Domain or subdomain name.', max_length=256, unique=True, validators=[orchestra.contrib.domains.validators.validate_domain_name, orchestra.contrib.domains.validators.validate_allowed_domain], verbose_name='name'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='domain',
|
||||||
|
name='top',
|
||||||
|
field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subdomain_set', to='domains.Domain', verbose_name='top domain'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='domain',
|
||||||
|
name='dns2136_address_match_list',
|
||||||
|
field=models.CharField(blank=True, default='key pangea.key;', help_text="A bind-9 'address_match_list' that will be granted permission to perform dns2136 updates. Chiefly used to enable Let's Encrypt self-service validation.", max_length=80),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,83 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.10.5 on 2021-04-22 11:27
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
import orchestra.contrib.domains.utils
|
|
||||||
import orchestra.contrib.domains.validators
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
replaces = [('domains', '0001_initial'), ('domains', '0002_auto_20150715_1017'), ('domains', '0003_auto_20150720_1121'), ('domains', '0004_auto_20150720_1121'), ('domains', '0005_auto_20160219_1034'), ('domains', '0006_auto_20170528_2011'), ('domains', '0007_auto_20190805_1134'), ('domains', '0008_domain_dns2136_address_match_list'), ('domains', '0009_auto_20200204_1217'), ('domains', '0010_auto_20210330_1049')]
|
|
||||||
|
|
||||||
initial = True
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Domain',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('name', models.CharField(help_text='Domain or subdomain name.', max_length=256, unique=True, validators=[orchestra.contrib.domains.validators.validate_domain_name, orchestra.contrib.domains.validators.validate_allowed_domain], verbose_name='name')),
|
|
||||||
('serial', models.IntegerField(default=orchestra.contrib.domains.utils.generate_zone_serial, help_text='Serial number', verbose_name='serial')),
|
|
||||||
('account', models.ForeignKey(blank=True, help_text='Automatically selected for subdomains.', on_delete=django.db.models.deletion.CASCADE, related_name='domains', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
|
|
||||||
('top', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subdomain_set', to='domains.Domain')),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Record',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('ttl', models.CharField(blank=True, help_text='Record TTL, defaults to 1h', max_length=8, validators=[orchestra.contrib.domains.validators.validate_zone_interval], verbose_name='TTL')),
|
|
||||||
('type', models.CharField(choices=[('MX', 'MX'), ('NS', 'NS'), ('CNAME', 'CNAME'), ('A', 'A (IPv4 address)'), ('AAAA', 'AAAA (IPv6 address)'), ('SRV', 'SRV'), ('TXT', 'TXT'), ('SPF', 'SPF')], max_length=32, verbose_name='type')),
|
|
||||||
('value', models.CharField(help_text='MX, NS and CNAME records sould end with a dot.', max_length=1024, verbose_name='value')),
|
|
||||||
('domain', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='records', to='domains.Domain', verbose_name='domain')),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='domain',
|
|
||||||
name='serial',
|
|
||||||
field=models.IntegerField(default=orchestra.contrib.domains.utils.generate_zone_serial, editable=False, help_text='A revision number that changes whenever this domain is updated.', verbose_name='serial'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='domain',
|
|
||||||
name='expire',
|
|
||||||
field=models.CharField(blank=True, help_text='The time that a secondary server will keep trying to complete a zone transfer. If this time expires prior to a successful zone transfer, the secondary server will expire its zone file. This means the secondary will stop answering queries. The default value is <tt>4w</tt>.', max_length=16, validators=[orchestra.contrib.domains.validators.validate_zone_interval], verbose_name='expire'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='domain',
|
|
||||||
name='min_ttl',
|
|
||||||
field=models.CharField(blank=True, help_text='The minimum time-to-live value applies to all resource records in the zone file. This value is supplied in query responses to inform other servers how long they should keep the data in cache. The default value is <tt>1h</tt>.', max_length=16, validators=[orchestra.contrib.domains.validators.validate_zone_interval], verbose_name='min TTL'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='domain',
|
|
||||||
name='refresh',
|
|
||||||
field=models.CharField(blank=True, help_text="The time a secondary DNS server waits before querying the primary DNS server's SOA record to check for changes. When the refresh time expires, the secondary DNS server requests a copy of the current SOA record from the primary. The primary DNS server complies with this request. The secondary DNS server compares the serial number of the primary DNS server's current SOA record and the serial number in it's own SOA record. If they are different, the secondary DNS server will request a zone transfer from the primary DNS server. The default value is <tt>1d</tt>.", max_length=16, validators=[orchestra.contrib.domains.validators.validate_zone_interval], verbose_name='refresh'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='domain',
|
|
||||||
name='retry',
|
|
||||||
field=models.CharField(blank=True, help_text='The time a secondary server waits before retrying a failed zone transfer. Normally, the retry time is less than the refresh time. The default value is <tt>2h</tt>.', max_length=16, validators=[orchestra.contrib.domains.validators.validate_zone_interval], verbose_name='retry'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='domain',
|
|
||||||
name='name',
|
|
||||||
field=models.CharField(db_index=True, help_text='Domain or subdomain name.', max_length=256, unique=True, validators=[orchestra.contrib.domains.validators.validate_domain_name, orchestra.contrib.domains.validators.validate_allowed_domain], verbose_name='name'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='domain',
|
|
||||||
name='top',
|
|
||||||
field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subdomain_set', to='domains.Domain', verbose_name='top domain'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='domain',
|
|
||||||
name='dns2136_address_match_list',
|
|
||||||
field=models.CharField(blank=True, default='key pangea.key;', help_text="A bind-9 'address_match_list' that will be granted permission to perform dns2136 updates. Chiefly used to enable Let's Encrypt self-service validation.", max_length=80),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,39 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import models, migrations
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('domains', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='domain',
|
|
||||||
name='expire',
|
|
||||||
field=models.IntegerField(null=True, blank=True, help_text='The upper limit in seconds before a zone is considered no longer authoritative (4w by default).', verbose_name='expire'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='domain',
|
|
||||||
name='min_ttl',
|
|
||||||
field=models.IntegerField(null=True, blank=True, help_text='The negative result TTL (for example, how long a resolver should consider a negative result for a subdomain to be valid before retrying) (1h by default).', verbose_name='refresh'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='domain',
|
|
||||||
name='refresh',
|
|
||||||
field=models.IntegerField(null=True, blank=True, help_text='The number of seconds before the zone should be refreshed (1d by default).', verbose_name='refresh'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='domain',
|
|
||||||
name='retry',
|
|
||||||
field=models.IntegerField(null=True, blank=True, help_text='The number of seconds before a failed refresh should be retried (2h by default).', verbose_name='retry'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='record',
|
|
||||||
name='value',
|
|
||||||
field=models.CharField(max_length=256, help_text='MX, NS and CNAME records sould end with a dot.', verbose_name='value'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,6 +1,4 @@
|
||||||
# -*- coding: utf-8 -*-
|
# Generated by Django 2.2.24 on 2024-07-11 12:25
|
||||||
# Generated by Django 1.10.5 on 2017-05-28 18:11
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import orchestra.contrib.domains.validators
|
import orchestra.contrib.domains.validators
|
||||||
|
@ -9,7 +7,7 @@ import orchestra.contrib.domains.validators
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('domains', '0005_auto_20160219_1034'),
|
('domains', '0001_initial'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
|
@ -26,6 +24,6 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='record',
|
model_name='record',
|
||||||
name='type',
|
name='type',
|
||||||
field=models.CharField(choices=[('MX', 'MX'), ('NS', 'NS'), ('CNAME', 'CNAME'), ('A', 'A (IPv4 address)'), ('AAAA', 'AAAA (IPv6 address)'), ('SRV', 'SRV'), ('TXT', 'TXT'), ('SPF', 'SPF')], max_length=32, verbose_name='type'),
|
field=models.CharField(choices=[('MX', 'MX'), ('NS', 'NS'), ('CNAME', 'CNAME'), ('A', 'A (IPv4 address)'), ('AAAA', 'AAAA (IPv6 address)'), ('SRV', 'SRV'), ('TXT', 'TXT'), ('SPF', 'SPF'), ('CAA', 'CAA')], max_length=32, verbose_name='type'),
|
||||||
),
|
),
|
||||||
]
|
]
|
|
@ -1,36 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import models, migrations
|
|
||||||
import orchestra.contrib.domains.utils
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('domains', '0002_auto_20150715_1017'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='domain',
|
|
||||||
name='expire',
|
|
||||||
),
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='domain',
|
|
||||||
name='min_ttl',
|
|
||||||
),
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='domain',
|
|
||||||
name='refresh',
|
|
||||||
),
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='domain',
|
|
||||||
name='retry',
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='domain',
|
|
||||||
name='serial',
|
|
||||||
field=models.IntegerField(editable=False, verbose_name='serial', default=orchestra.contrib.domains.utils.generate_zone_serial, help_text='A revision number that changes whenever this domain is updated.'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,35 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import models, migrations
|
|
||||||
import orchestra.contrib.domains.validators
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('domains', '0003_auto_20150720_1121'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='domain',
|
|
||||||
name='expire',
|
|
||||||
field=models.CharField(validators=[orchestra.contrib.domains.validators.validate_zone_interval], blank=True, help_text='The time that a secondary server will keep trying to complete a zone transfer. If this time expires prior to a successful zone transfer, the secondary server will expire its zone file. This means the secondary will stop answering queries. The default value is <tt>4w</tt>.', verbose_name='expire', max_length=16),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='domain',
|
|
||||||
name='min_ttl',
|
|
||||||
field=models.CharField(validators=[orchestra.contrib.domains.validators.validate_zone_interval], blank=True, help_text='The minimum time-to-live value applies to all resource records in the zone file. This value is supplied in query responses to inform other servers how long they should keep the data in cache. The default value is <tt>1h</tt>.', verbose_name='min TTL', max_length=16),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='domain',
|
|
||||||
name='refresh',
|
|
||||||
field=models.CharField(validators=[orchestra.contrib.domains.validators.validate_zone_interval], blank=True, help_text="The time a secondary DNS server waits before querying the primary DNS server's SOA record to check for changes. When the refresh time expires, the secondary DNS server requests a copy of the current SOA record from the primary. The primary DNS server complies with this request. The secondary DNS server compares the serial number of the primary DNS server's current SOA record and the serial number in it's own SOA record. If they are different, the secondary DNS server will request a zone transfer from the primary DNS server. The default value is <tt>1d</tt>.", verbose_name='refresh', max_length=16),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='domain',
|
|
||||||
name='retry',
|
|
||||||
field=models.CharField(validators=[orchestra.contrib.domains.validators.validate_zone_interval], blank=True, help_text='The time a secondary server waits before retrying a failed zone transfer. Normally, the retry time is less than the refresh time. The default value is <tt>2h</tt>.', verbose_name='retry', max_length=16),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,31 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
import orchestra.contrib.domains.validators
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('domains', '0004_auto_20150720_1121'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='domain',
|
|
||||||
name='name',
|
|
||||||
field=models.CharField(max_length=256, validators=[orchestra.contrib.domains.validators.validate_domain_name, orchestra.contrib.domains.validators.validate_allowed_domain], db_index=True, verbose_name='name', unique=True, help_text='Domain or subdomain name.'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='domain',
|
|
||||||
name='top',
|
|
||||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, editable=False, verbose_name='top domain', related_name='subdomain_set', to='domains.Domain', null=True),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='record',
|
|
||||||
name='type',
|
|
||||||
field=models.CharField(max_length=32, verbose_name='type', choices=[('MX', 'MX'), ('NS', 'NS'), ('CNAME', 'CNAME'), ('A', 'A (IPv4 address)'), ('AAAA', 'AAAA (IPv6 address)'), ('SRV', 'SRV'), ('TXT', 'TXT'), ('SPF', 'SPF'), ('SOA', 'SOA')]),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,20 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.10.5 on 2019-08-05 09:34
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('domains', '0006_auto_20170528_2011'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='record',
|
|
||||||
name='value',
|
|
||||||
field=models.CharField(help_text='MX, NS and CNAME records sould end with a dot.', max_length=1024, verbose_name='value'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,20 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.10.5 on 2019-09-20 07:21
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('domains', '0007_auto_20190805_1134'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='domain',
|
|
||||||
name='dns2136_address_match_list',
|
|
||||||
field=models.CharField(blank=True, default='none;', help_text="A bind-9 'address_match_list' that will be granted permission to perform dns2136 updates. Chiefly used to enable Let's Encrypt self-service validation.", max_length=80),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,20 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.10.5 on 2020-02-04 11:17
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('domains', '0008_domain_dns2136_address_match_list'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='domain',
|
|
||||||
name='dns2136_address_match_list',
|
|
||||||
field=models.CharField(blank=True, default='key pangea.key;', help_text="A bind-9 'address_match_list' that will be granted permission to perform dns2136 updates. Chiefly used to enable Let's Encrypt self-service validation.", max_length=80),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,26 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.10.5 on 2021-03-30 10:49
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import orchestra.contrib.domains.validators
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('domains', '0009_auto_20200204_1217'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='domain',
|
|
||||||
name='min_ttl',
|
|
||||||
field=models.CharField(blank=True, help_text='The minimum time-to-live value applies to all resource records in the zone file. This value is supplied in query responses to inform other servers how long they should keep the data in cache. The default value is <tt>1h</tt>.', max_length=16, validators=[orchestra.contrib.domains.validators.validate_zone_interval], verbose_name='min TTL'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='record',
|
|
||||||
name='ttl',
|
|
||||||
field=models.CharField(blank=True, help_text='Record TTL, defaults to 1h', max_length=8, validators=[orchestra.contrib.domains.validators.validate_zone_interval], verbose_name='TTL'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -145,8 +145,9 @@ class Domain(models.Model):
|
||||||
else:
|
else:
|
||||||
zone += subdomain.render_records()
|
zone += subdomain.render_records()
|
||||||
###darmengo 2021-03-25 add autoconfig
|
###darmengo 2021-03-25 add autoconfig
|
||||||
|
# TODO: que se asigne esta ip automaticamente
|
||||||
if self.has_default_mx():
|
if self.has_default_mx():
|
||||||
zone += 'autoconfig.{}. 30m IN A 109.69.8.133\n'.format(self.name)
|
zone += 'autoconfig.{}. 30m IN A 45.150.186.197\n'.format(self.name)
|
||||||
###END darmengo 2021-03-25 add autoconfig
|
###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()
|
||||||
|
@ -298,6 +299,7 @@ class Record(models.Model):
|
||||||
TXT = 'TXT'
|
TXT = 'TXT'
|
||||||
SPF = 'SPF'
|
SPF = 'SPF'
|
||||||
SOA = 'SOA'
|
SOA = 'SOA'
|
||||||
|
CAA = 'CAA'
|
||||||
|
|
||||||
TYPE_CHOICES = (
|
TYPE_CHOICES = (
|
||||||
(MX, "MX"),
|
(MX, "MX"),
|
||||||
|
@ -308,6 +310,7 @@ class Record(models.Model):
|
||||||
(SRV, "SRV"),
|
(SRV, "SRV"),
|
||||||
(TXT, "TXT"),
|
(TXT, "TXT"),
|
||||||
(SPF, "SPF"),
|
(SPF, "SPF"),
|
||||||
|
(CAA, "CAA"),
|
||||||
)
|
)
|
||||||
|
|
||||||
VALIDATORS = {
|
VALIDATORS = {
|
||||||
|
@ -320,6 +323,7 @@ class Record(models.Model):
|
||||||
SPF: (validate_ascii, validators.validate_quoted_record),
|
SPF: (validate_ascii, validators.validate_quoted_record),
|
||||||
SRV: (validators.validate_srv_record,),
|
SRV: (validators.validate_srv_record,),
|
||||||
SOA: (validators.validate_soa_record,),
|
SOA: (validators.validate_soa_record,),
|
||||||
|
CAA: (validators.validate_caa_record,),
|
||||||
}
|
}
|
||||||
|
|
||||||
domain = models.ForeignKey(Domain, verbose_name=_("domain"), related_name='records', on_delete=models.CASCADE)
|
domain = models.ForeignKey(Domain, verbose_name=_("domain"), related_name='records', on_delete=models.CASCADE)
|
||||||
|
|
|
@ -53,7 +53,7 @@ def validate_zone_label(value):
|
||||||
Labels may not be all numbers, but may have a leading digit (e.g., 3com.com).
|
Labels may not be all numbers, but may have a leading digit (e.g., 3com.com).
|
||||||
Labels must end and begin only with a letter or digit. See [RFC 1035] and [RFC 1123].
|
Labels must end and begin only with a letter or digit. See [RFC 1035] and [RFC 1123].
|
||||||
"""
|
"""
|
||||||
if not re.match(r'^[a-z0-9][\.\-0-9a-z]*[\.0-9a-z]$', value):
|
if not re.match(r'^[a-z0-9][\.\-0-9a-z_]*[\.0-9a-z]$', value):
|
||||||
msg = _("Labels must start and end with a letter or digit, "
|
msg = _("Labels must start and end with a letter or digit, "
|
||||||
"and have as interior characters only letters, digits, and hyphen.")
|
"and have as interior characters only letters, digits, and hyphen.")
|
||||||
raise ValidationError(msg)
|
raise ValidationError(msg)
|
||||||
|
@ -105,6 +105,28 @@ def validate_soa_record(value):
|
||||||
raise ValidationError(msg)
|
raise ValidationError(msg)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_caa_record(value):
|
||||||
|
# 0-255 issue|issuewild|iodef "domain|mailto:email"
|
||||||
|
# 0 issue "letsewncript.org"
|
||||||
|
msg = _("%s is not an appropiate CAA record value, sintax: 0-255 issue|issuewild|iodef \"domain|mailto:email\"") % value
|
||||||
|
values = value.split()
|
||||||
|
if len(values) != 3:
|
||||||
|
raise ValidationError(msg)
|
||||||
|
|
||||||
|
patron_flag = r'^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
|
||||||
|
patron_tag = r'^(issue|issuewild|iodef)$'
|
||||||
|
patron_value_domain = r'^"[a-zA-Z0-9-.]+\.[a-zA-Z]+\.?"$'
|
||||||
|
patron_value_mailto = r'^"mailto:[a-zA-Z0-9.]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"$'
|
||||||
|
flag = re.match(patron_flag, values[0])
|
||||||
|
tag = re.match(patron_tag, values[1])
|
||||||
|
if values[1] == 'iodef':
|
||||||
|
valor = re.match(patron_value_mailto, values[2])
|
||||||
|
else:
|
||||||
|
valor = re.match(patron_value_domain, values[2])
|
||||||
|
if not (flag and tag and valor):
|
||||||
|
raise ValidationError(msg)
|
||||||
|
|
||||||
|
|
||||||
def validate_quoted_record(value):
|
def validate_quoted_record(value):
|
||||||
value = value.strip()
|
value = value.strip()
|
||||||
if ' ' in value and (value[0] != '"' or value[-1] != '"'):
|
if ' ' in value and (value[0] != '"' or value[-1] != '"'):
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
default_app_config = 'orchestra.contrib.history.apps.HistoryConfig'
|
|
@ -36,10 +36,6 @@ class LogEntryAdmin(admin.ModelAdmin):
|
||||||
user_link = admin_link('user')
|
user_link = admin_link('user')
|
||||||
display_action_time = admin_date('action_time', short_description=_("Time"))
|
display_action_time = admin_date('action_time', short_description=_("Time"))
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("Message"),
|
|
||||||
ordering='action_flag',
|
|
||||||
)
|
|
||||||
@mark_safe
|
@mark_safe
|
||||||
def display_message(self, log):
|
def display_message(self, log):
|
||||||
edit = format_html('<a href="{url}"><img src="{img}"></img></a>', **{
|
edit = format_html('<a href="{url}"><img src="{img}"></img></a>', **{
|
||||||
|
@ -62,22 +58,18 @@ class LogEntryAdmin(admin.ModelAdmin):
|
||||||
'object': log.object_repr,
|
'object': log.object_repr,
|
||||||
'edit': edit,
|
'edit': edit,
|
||||||
}
|
}
|
||||||
|
display_message.short_description = _("Message")
|
||||||
|
display_message.admin_order_field = 'action_flag'
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("Action"),
|
|
||||||
ordering='action_flag',
|
|
||||||
)
|
|
||||||
def display_action(self, log):
|
def display_action(self, log):
|
||||||
if log.is_addition():
|
if log.is_addition():
|
||||||
return _("Added")
|
return _("Added")
|
||||||
elif log.is_change():
|
elif log.is_change():
|
||||||
return _("Changed")
|
return _("Changed")
|
||||||
return _("Deleted")
|
return _("Deleted")
|
||||||
|
display_action.short_description = _("Action")
|
||||||
|
display_action.admin_order_field = 'action_flag'
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("Content object"),
|
|
||||||
ordering='object_repr',
|
|
||||||
)
|
|
||||||
def content_object_link(self, log):
|
def content_object_link(self, log):
|
||||||
ct = log.content_type
|
ct = log.content_type
|
||||||
view = 'admin:%s_%s_change' % (ct.app_label, ct.model)
|
view = 'admin:%s_%s_change' % (ct.app_label, ct.model)
|
||||||
|
@ -86,6 +78,8 @@ class LogEntryAdmin(admin.ModelAdmin):
|
||||||
except NoReverseMatch:
|
except NoReverseMatch:
|
||||||
return log.object_repr
|
return log.object_repr
|
||||||
return format_html('<a href="{}">{}</a>', url, log.object_repr)
|
return format_html('<a href="{}">{}</a>', url, log.object_repr)
|
||||||
|
content_object_link.short_description = _("Content object")
|
||||||
|
content_object_link.admin_order_field = 'object_repr'
|
||||||
|
|
||||||
def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
|
def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
|
||||||
""" Add rel_opts and object to context """
|
""" Add rel_opts and object to context """
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
BBBBBBB BBBBBBBBBBBBBBBBBBBBBBBB
|
||||||
|
BBBB BBBB BBBBBBBBBB
|
||||||
|
|
||||||
|
BBBBB BBBBBBBBBBBBBBBBBB
|
||||||
|
BBBBBBBB
|
||||||
|
|
||||||
|
|
||||||
|
BBBBB BBBBBBBBBBB
|
||||||
|
BB BBBBBBBB
|
||||||
|
XXXX XXXXXXXXXXXXXXXXXXXX
|
||||||
|
XX XXXXXXBBB BBBBBBBBBBBBBXX gettext(u'Home') XXXX
|
||||||
|
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBXXXXXX
|
||||||
|
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXFFFFFFFFXXXX
|
||||||
|
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXFFFFFFFFFFFFFFFFFFXXXX
|
||||||
|
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXX gettext(u'History') XXXX
|
||||||
|
XXXXXXXX gettext(u'Edit')
|
||||||
|
XXXXXX
|
||||||
|
BBBB
|
||||||
|
|
||||||
|
BBBBB
|
||||||
|
BBBBBBBB
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
BBBBBBB BBBBBBBBBBBBBBBBBBBBBB
|
||||||
|
BBBB BBBB BBBBBBBBBB BBBBBB
|
||||||
|
|
||||||
|
BBBBB BBBBBBBBBBB
|
||||||
|
XXXX XXXXXXXXXXXXXXXXXXXX
|
||||||
|
XX XXXXXXBBB BBBBBBBBBBBBBXX gettext(u'Home') XXXX
|
||||||
|
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBXXXXXX
|
||||||
|
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXXXXX
|
||||||
|
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBXXFFFFFFFFFFFFFFFFFFXXXX
|
||||||
|
XXXXXXXX gettext(u'History')
|
||||||
|
XXXXXX
|
||||||
|
BBBBBBBB
|
||||||
|
|
||||||
|
BBBBB BBBBBBB
|
||||||
|
XXXX XXXXXXXXXXXXXXXXXX
|
||||||
|
XXXX XXXXXXXXXXXXXXX
|
||||||
|
|
||||||
|
BB BBBBBBBBBBB
|
||||||
|
XXXXXX XXXXXXXXXXXXXXXXXXXX
|
||||||
|
XXXXXXX
|
||||||
|
XXXX
|
||||||
|
XXX XXXXXXXXXXXX gettext(u'Date/time') XXXXX
|
||||||
|
XXX XXXXXXXXXXXX gettext(u'User') XXXXX
|
||||||
|
XXX XXXXXXXXXXXX gettext(u'Action') XXXXX
|
||||||
|
XXXXX
|
||||||
|
XXXXXXXX
|
||||||
|
XXXXXXX
|
||||||
|
BBB BBBBBB BB BBBBBBBBBBB
|
||||||
|
XXXX
|
||||||
|
XXX XXXXXXXXXXXXFFFFFFFFFFFFFFFFFFFFFFXXXXX
|
||||||
|
XXXXBB BBBBBBBBBBBBBBBBBBBBBBBBB XXBBBBBXXXXX
|
||||||
|
XXXXBB BBBBBBBBBBBBBBBBBB BBB BBB BBBBBBBBBBBBBBBBBBBBB gettext(u'Added') BBBBBBBBB XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXX XXXXXBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXXXXXXXXXXXXXXXX
|
||||||
|
XXXXX
|
||||||
|
BBBBBB
|
||||||
|
XXXXXXXX
|
||||||
|
XXXXXXXX
|
||||||
|
BBBB
|
||||||
|
XXX gettext(u"This object doesn't have a change history. It probably wasn't added via this admin site.") XXXX
|
||||||
|
BBBBB
|
||||||
|
XXXXXX
|
||||||
|
XXXXXX
|
||||||
|
BBBBBBBB
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
default_app_config = 'orchestra.contrib.issues.apps.IssuesConfig'
|
|
@ -51,9 +51,6 @@ class MessageReadOnlyInline(admin.TabularInline):
|
||||||
'all': ('orchestra/css/hide-inline-id.css',)
|
'all': ('orchestra/css/hide-inline-id.css',)
|
||||||
}
|
}
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("Content")
|
|
||||||
)
|
|
||||||
@mark_safe
|
@mark_safe
|
||||||
def content_html(self, msg):
|
def content_html(self, msg):
|
||||||
context = {
|
context = {
|
||||||
|
@ -69,6 +66,7 @@ class MessageReadOnlyInline(admin.TabularInline):
|
||||||
content = '<div style="padding-left:20px;">%s</div>' % content
|
content = '<div style="padding-left:20px;">%s</div>' % content
|
||||||
|
|
||||||
return header + content
|
return header + content
|
||||||
|
content_html.short_description = _("Content")
|
||||||
|
|
||||||
def has_add_permission(self, request, obj):
|
def has_add_permission(self, request, obj):
|
||||||
return False
|
return False
|
||||||
|
@ -116,15 +114,12 @@ class TicketInline(admin.TabularInline):
|
||||||
colored_state = admin_colored('state', colors=STATE_COLORS, bold=False)
|
colored_state = admin_colored('state', colors=STATE_COLORS, bold=False)
|
||||||
colored_priority = admin_colored('priority', colors=PRIORITY_COLORS, bold=False)
|
colored_priority = admin_colored('priority', colors=PRIORITY_COLORS, bold=False)
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description='#'
|
|
||||||
)
|
|
||||||
@mark_safe
|
@mark_safe
|
||||||
def ticket_id(self, instance):
|
def ticket_id(self, instance):
|
||||||
return '<b>%s</b>' % admin_link()(instance)
|
return '<b>%s</b>' % admin_link()(instance)
|
||||||
|
ticket_id.short_description = '#'
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Ticket)
|
|
||||||
class TicketAdmin(ExtendedModelAdmin):
|
class TicketAdmin(ExtendedModelAdmin):
|
||||||
list_display = (
|
list_display = (
|
||||||
'unbold_id', 'bold_subject', 'display_creator', 'display_owner',
|
'unbold_id', 'bold_subject', 'display_creator', 'display_owner',
|
||||||
|
@ -200,9 +195,6 @@ class TicketAdmin(ExtendedModelAdmin):
|
||||||
display_state = admin_colored('state', colors=STATE_COLORS, bold=False)
|
display_state = admin_colored('state', colors=STATE_COLORS, bold=False)
|
||||||
display_priority = admin_colored('priority', colors=PRIORITY_COLORS, bold=False)
|
display_priority = admin_colored('priority', colors=PRIORITY_COLORS, bold=False)
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description='Summary'
|
|
||||||
)
|
|
||||||
@mark_safe
|
@mark_safe
|
||||||
def display_summary(self, ticket):
|
def display_summary(self, ticket):
|
||||||
context = {
|
context = {
|
||||||
|
@ -218,26 +210,23 @@ class TicketAdmin(ExtendedModelAdmin):
|
||||||
})
|
})
|
||||||
context['updated'] = '. Updated by %(updater)s about %(updated)s' % context
|
context['updated'] = '. Updated by %(updater)s about %(updated)s' % context
|
||||||
return '<h4>Added by %(creator)s about %(created)s%(updated)s</h4>' % context
|
return '<h4>Added by %(creator)s about %(created)s%(updated)s</h4>' % context
|
||||||
|
display_summary.short_description = 'Summary'
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description="#",
|
|
||||||
ordering='id',
|
|
||||||
)
|
|
||||||
def unbold_id(self, ticket):
|
def unbold_id(self, ticket):
|
||||||
""" Unbold id if ticket is read """
|
""" Unbold id if ticket is read """
|
||||||
if ticket.is_read_by(self.user):
|
if ticket.is_read_by(self.user):
|
||||||
return format_html('<span style="font-weight:normal;font-size:11px;">{}</span>', ticket.pk)
|
return format_html('<span style="font-weight:normal;font-size:11px;">{}</span>', ticket.pk)
|
||||||
return ticket.pk
|
return ticket.pk
|
||||||
|
unbold_id.short_description = "#"
|
||||||
|
unbold_id.admin_order_field = 'id'
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("Subject"),
|
|
||||||
ordering='subject',
|
|
||||||
)
|
|
||||||
def bold_subject(self, ticket):
|
def bold_subject(self, ticket):
|
||||||
""" Bold subject when tickets are unread for request.user """
|
""" Bold subject when tickets are unread for request.user """
|
||||||
if ticket.is_read_by(self.user):
|
if ticket.is_read_by(self.user):
|
||||||
return ticket.subject
|
return ticket.subject
|
||||||
return format_html("<strong class='unread'>{}</strong>", ticket.subject)
|
return format_html("<strong class='unread'>{}</strong>", ticket.subject)
|
||||||
|
bold_subject.short_description = _("Subject")
|
||||||
|
bold_subject.admin_order_field = 'subject'
|
||||||
|
|
||||||
def formfield_for_dbfield(self, db_field, **kwargs):
|
def formfield_for_dbfield(self, db_field, **kwargs):
|
||||||
""" Make value input widget bigger """
|
""" Make value input widget bigger """
|
||||||
|
@ -294,7 +283,6 @@ class TicketAdmin(ExtendedModelAdmin):
|
||||||
return HttpResponse(data_formated)
|
return HttpResponse(data_formated)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Queue)
|
|
||||||
class QueueAdmin(admin.ModelAdmin):
|
class QueueAdmin(admin.ModelAdmin):
|
||||||
list_display = ('name', 'default', 'num_tickets')
|
list_display = ('name', 'default', 'num_tickets')
|
||||||
actions = (set_default_queue,)
|
actions = (set_default_queue,)
|
||||||
|
@ -306,15 +294,13 @@ class QueueAdmin(admin.ModelAdmin):
|
||||||
'all': ('orchestra/css/hide-inline-id.css',)
|
'all': ('orchestra/css/hide-inline-id.css',)
|
||||||
}
|
}
|
||||||
|
|
||||||
@admin.display(
|
|
||||||
description=_("Tickets"),
|
|
||||||
ordering='tickets__count',
|
|
||||||
)
|
|
||||||
def num_tickets(self, queue):
|
def num_tickets(self, queue):
|
||||||
num = queue.tickets__count
|
num = queue.tickets__count
|
||||||
url = reverse('admin:issues_ticket_changelist')
|
url = reverse('admin:issues_ticket_changelist')
|
||||||
url += '?queue=%i' % queue.pk
|
url += '?queue=%i' % queue.pk
|
||||||
return format_html('<a href="{}">{}</a>', url, num)
|
return format_html('<a href="{}">{}</a>', url, num)
|
||||||
|
num_tickets.short_description = _("Tickets")
|
||||||
|
num_tickets.admin_order_field = 'tickets__count'
|
||||||
|
|
||||||
def get_list_display(self, request):
|
def get_list_display(self, request):
|
||||||
""" show notifications """
|
""" show notifications """
|
||||||
|
@ -333,3 +319,5 @@ class QueueAdmin(admin.ModelAdmin):
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
|
|
||||||
|
admin.site.register(Ticket, TicketAdmin)
|
||||||
|
admin.site.register(Queue, QueueAdmin)
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.5 on 2021-04-22 11:27
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.db.models.deletion
|
import datetime
|
||||||
from django.db import models, migrations
|
|
||||||
import orchestra.models.fields
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.utils.timezone import utc
|
||||||
|
import orchestra.models.fields
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
@ -17,7 +20,7 @@ class Migration(migrations.Migration):
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Message',
|
name='Message',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(primary_key=True, serialize=False, auto_created=True, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('author_name', models.CharField(blank=True, max_length=256, verbose_name='author name')),
|
('author_name', models.CharField(blank=True, max_length=256, verbose_name='author name')),
|
||||||
('content', models.TextField(verbose_name='content')),
|
('content', models.TextField(verbose_name='content')),
|
||||||
('created_on', models.DateTimeField(auto_now_add=True, verbose_name='created on')),
|
('created_on', models.DateTimeField(auto_now_add=True, verbose_name='created on')),
|
||||||
|
@ -30,28 +33,28 @@ class Migration(migrations.Migration):
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Queue',
|
name='Queue',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(primary_key=True, serialize=False, auto_created=True, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('name', models.CharField(max_length=128, verbose_name='name', unique=True)),
|
('name', models.CharField(max_length=128, unique=True, verbose_name='name')),
|
||||||
('verbose_name', models.CharField(blank=True, max_length=128, verbose_name='verbose_name')),
|
('verbose_name', models.CharField(blank=True, max_length=128, verbose_name='verbose_name')),
|
||||||
('default', models.BooleanField(verbose_name='default', default=False)),
|
('default', models.BooleanField(default=False, verbose_name='default')),
|
||||||
('notify', orchestra.models.fields.MultiSelectField(blank=True, max_length=256, help_text='Contacts to notify by email', verbose_name='notify', default=('SUPPORT', 'ADMIN', 'BILLING', 'TECH', 'ADDS', 'EMERGENCY'), choices=[('SUPPORT', 'Support tickets'), ('ADMIN', 'Administrative'), ('BILLING', 'Billing'), ('TECH', 'Technical'), ('ADDS', 'Announcements'), ('EMERGENCY', 'Emergency contact')])),
|
('notify', orchestra.models.fields.MultiSelectField(blank=True, choices=[('SUPPORT', 'Support tickets'), ('ADMIN', 'Administrative'), ('BILLING', 'Billing'), ('TECH', 'Technical'), ('ADDS', 'Announcements'), ('EMERGENCY', 'Emergency contact')], default=('SUPPORT', 'ADMIN', 'BILLING', 'TECH', 'ADDS', 'EMERGENCY'), help_text='Contacts to notify by email', max_length=256, verbose_name='notify')),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Ticket',
|
name='Ticket',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(primary_key=True, serialize=False, auto_created=True, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('creator_name', models.CharField(blank=True, max_length=256, verbose_name='creator name')),
|
('creator_name', models.CharField(blank=True, max_length=256, verbose_name='creator name')),
|
||||||
('subject', models.CharField(max_length=256, verbose_name='subject')),
|
('subject', models.CharField(max_length=256, verbose_name='subject')),
|
||||||
('description', models.TextField(verbose_name='description')),
|
('description', models.TextField(verbose_name='description')),
|
||||||
('priority', models.CharField(max_length=32, default='MEDIUM', verbose_name='priority', choices=[('HIGH', 'High'), ('MEDIUM', 'Medium'), ('LOW', 'Low')])),
|
('priority', models.CharField(choices=[('HIGH', 'High'), ('MEDIUM', 'Medium'), ('LOW', 'Low')], default='MEDIUM', max_length=32, verbose_name='priority')),
|
||||||
('state', models.CharField(max_length=32, default='NEW', verbose_name='state', choices=[('NEW', 'New'), ('IN_PROGRESS', 'In Progress'), ('RESOLVED', 'Resolved'), ('FEEDBACK', 'Feedback'), ('REJECTED', 'Rejected'), ('CLOSED', 'Closed')])),
|
('state', models.CharField(choices=[('NEW', 'New'), ('IN_PROGRESS', 'In Progress'), ('RESOLVED', 'Resolved'), ('FEEDBACK', 'Feedback'), ('REJECTED', 'Rejected'), ('CLOSED', 'Closed')], default='NEW', max_length=32, verbose_name='state')),
|
||||||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='created')),
|
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='created')),
|
||||||
('updated_at', models.DateTimeField(auto_now=True, verbose_name='modified')),
|
('updated_at', models.DateTimeField(auto_now=True, verbose_name='modified')),
|
||||||
('cc', models.TextField(blank=True, help_text='emails to send a carbon copy to', verbose_name='CC')),
|
('cc', models.TextField(blank=True, help_text='emails to send a carbon copy to', verbose_name='CC')),
|
||||||
('creator', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tickets_created', null=True, to=settings.AUTH_USER_MODEL, verbose_name='created by')),
|
('creator', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tickets_created', to=settings.AUTH_USER_MODEL, verbose_name='created by')),
|
||||||
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, blank=True, related_name='tickets_owned', null=True, to=settings.AUTH_USER_MODEL, verbose_name='assigned to')),
|
('owner', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tickets_owned', to=settings.AUTH_USER_MODEL, verbose_name='assigned to')),
|
||||||
('queue', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, blank=True, related_name='tickets', null=True, to='issues.Queue')),
|
('queue', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tickets', to='issues.Queue')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'ordering': ['-updated_at'],
|
'ordering': ['-updated_at'],
|
||||||
|
@ -60,7 +63,7 @@ class Migration(migrations.Migration):
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='TicketTracker',
|
name='TicketTracker',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(primary_key=True, serialize=False, auto_created=True, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('ticket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='trackers', to='issues.Ticket', verbose_name='ticket')),
|
('ticket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='trackers', to='issues.Ticket', verbose_name='ticket')),
|
||||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_trackers', to=settings.AUTH_USER_MODEL, verbose_name='user')),
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_trackers', to=settings.AUTH_USER_MODEL, verbose_name='user')),
|
||||||
],
|
],
|
||||||
|
@ -74,4 +77,34 @@ class Migration(migrations.Migration):
|
||||||
name='tickettracker',
|
name='tickettracker',
|
||||||
unique_together=set([('ticket', 'user')]),
|
unique_together=set([('ticket', 'user')]),
|
||||||
),
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='ticket',
|
||||||
|
name='created_at',
|
||||||
|
field=models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='created'),
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='message',
|
||||||
|
name='created_on',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='message',
|
||||||
|
name='created_at',
|
||||||
|
field=models.DateTimeField(auto_now_add=True, default=datetime.datetime(2016, 3, 20, 10, 27, 45, 766388, tzinfo=utc), verbose_name='created at'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='ticket',
|
||||||
|
name='creator',
|
||||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tickets_created', to=settings.AUTH_USER_MODEL, verbose_name='created by'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='ticket',
|
||||||
|
name='owner',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tickets_owned', to=settings.AUTH_USER_MODEL, verbose_name='assigned to'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='ticket',
|
||||||
|
name='queue',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tickets', to='issues.Queue'),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,114 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.10.5 on 2021-04-22 11:27
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
import datetime
|
|
||||||
from django.conf import settings
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
from django.utils.timezone import utc
|
|
||||||
import orchestra.models.fields
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
replaces = [('issues', '0001_initial'), ('issues', '0002_auto_20150709_1018'), ('issues', '0003_auto_20160320_1127'), ('issues', '0004_auto_20170528_2011')]
|
|
||||||
|
|
||||||
initial = True
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Message',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('author_name', models.CharField(blank=True, max_length=256, verbose_name='author name')),
|
|
||||||
('content', models.TextField(verbose_name='content')),
|
|
||||||
('created_on', models.DateTimeField(auto_now_add=True, verbose_name='created on')),
|
|
||||||
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_messages', to=settings.AUTH_USER_MODEL, verbose_name='author')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'get_latest_by': 'id',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Queue',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('name', models.CharField(max_length=128, unique=True, verbose_name='name')),
|
|
||||||
('verbose_name', models.CharField(blank=True, max_length=128, verbose_name='verbose_name')),
|
|
||||||
('default', models.BooleanField(default=False, verbose_name='default')),
|
|
||||||
('notify', orchestra.models.fields.MultiSelectField(blank=True, choices=[('SUPPORT', 'Support tickets'), ('ADMIN', 'Administrative'), ('BILLING', 'Billing'), ('TECH', 'Technical'), ('ADDS', 'Announcements'), ('EMERGENCY', 'Emergency contact')], default=('SUPPORT', 'ADMIN', 'BILLING', 'TECH', 'ADDS', 'EMERGENCY'), help_text='Contacts to notify by email', max_length=256, verbose_name='notify')),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Ticket',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('creator_name', models.CharField(blank=True, max_length=256, verbose_name='creator name')),
|
|
||||||
('subject', models.CharField(max_length=256, verbose_name='subject')),
|
|
||||||
('description', models.TextField(verbose_name='description')),
|
|
||||||
('priority', models.CharField(choices=[('HIGH', 'High'), ('MEDIUM', 'Medium'), ('LOW', 'Low')], default='MEDIUM', max_length=32, verbose_name='priority')),
|
|
||||||
('state', models.CharField(choices=[('NEW', 'New'), ('IN_PROGRESS', 'In Progress'), ('RESOLVED', 'Resolved'), ('FEEDBACK', 'Feedback'), ('REJECTED', 'Rejected'), ('CLOSED', 'Closed')], default='NEW', max_length=32, verbose_name='state')),
|
|
||||||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='created')),
|
|
||||||
('updated_at', models.DateTimeField(auto_now=True, verbose_name='modified')),
|
|
||||||
('cc', models.TextField(blank=True, help_text='emails to send a carbon copy to', verbose_name='CC')),
|
|
||||||
('creator', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tickets_created', to=settings.AUTH_USER_MODEL, verbose_name='created by')),
|
|
||||||
('owner', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tickets_owned', to=settings.AUTH_USER_MODEL, verbose_name='assigned to')),
|
|
||||||
('queue', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tickets', to='issues.Queue')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'ordering': ['-updated_at'],
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='TicketTracker',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('ticket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='trackers', to='issues.Ticket', verbose_name='ticket')),
|
|
||||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_trackers', to=settings.AUTH_USER_MODEL, verbose_name='user')),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='message',
|
|
||||||
name='ticket',
|
|
||||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='issues.Ticket', verbose_name='ticket'),
|
|
||||||
),
|
|
||||||
migrations.AlterUniqueTogether(
|
|
||||||
name='tickettracker',
|
|
||||||
unique_together=set([('ticket', 'user')]),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='ticket',
|
|
||||||
name='created_at',
|
|
||||||
field=models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='created'),
|
|
||||||
),
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='message',
|
|
||||||
name='created_on',
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='message',
|
|
||||||
name='created_at',
|
|
||||||
field=models.DateTimeField(auto_now_add=True, default=datetime.datetime(2016, 3, 20, 10, 27, 45, 766388, tzinfo=utc), verbose_name='created at'),
|
|
||||||
preserve_default=False,
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='ticket',
|
|
||||||
name='creator',
|
|
||||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tickets_created', to=settings.AUTH_USER_MODEL, verbose_name='created by'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='ticket',
|
|
||||||
name='owner',
|
|
||||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tickets_owned', to=settings.AUTH_USER_MODEL, verbose_name='assigned to'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='ticket',
|
|
||||||
name='queue',
|
|
||||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tickets', to='issues.Queue'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,19 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import models, migrations
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('issues', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='ticket',
|
|
||||||
name='created_at',
|
|
||||||
field=models.DateTimeField(db_index=True, auto_now_add=True, verbose_name='created'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,26 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import datetime
|
|
||||||
from django.utils.timezone import utc
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('issues', '0002_auto_20150709_1018'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='message',
|
|
||||||
name='created_on',
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='message',
|
|
||||||
name='created_at',
|
|
||||||
field=models.DateTimeField(auto_now_add=True, default=datetime.datetime(2016, 3, 20, 10, 27, 45, 766388, tzinfo=utc), verbose_name='created at'),
|
|
||||||
preserve_default=False,
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,32 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.10.5 on 2017-05-28 18:11
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('issues', '0003_auto_20160320_1127'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='ticket',
|
|
||||||
name='creator',
|
|
||||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tickets_created', to=settings.AUTH_USER_MODEL, verbose_name='created by'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='ticket',
|
|
||||||
name='owner',
|
|
||||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tickets_owned', to=settings.AUTH_USER_MODEL, verbose_name='assigned to'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='ticket',
|
|
||||||
name='queue',
|
|
||||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tickets', to='issues.Queue'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
XXXXXXXXX XXXX XXXXXX XXXXXXXXXXXX XXXXX XXX XXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||||
|
XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||||
|
XXXXXX
|
||||||
|
XXXXX XXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXX XX
|
||||||
|
XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXX XX
|
||||||
|
XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXX
|
||||||
|
XXXXXX XXXXXXXXXXXXXXXX
|
||||||
|
XX X XXXXXXXXXXXX XXXXXXXX XXXXXXXXXXX XXXXXXXXXX XXXXX XXXXXXXXXXX XXXXXXX XXXXXX XXXXX X
|
||||||
|
XXXX X XXXXXXXXXXXX XXXXXXXX XXXXXXXXXXX XXXXXXXXXX XXXXX XXXXXX XXXXX X
|
||||||
|
XXXXX XX X XXXXXXXXXXXX XXXX X
|
||||||
|
XXXXX XX X XXXXXXXXXXXXXXX XXXX XXXXXXXXXXXXXXXXX XXXXXXXX XXXXXXX XXXX XXXXXXXXXXXXXXX XXXXXXXX
|
||||||
|
XXXXX XX XXXX X XXXXXXXXXX XXXXXX X
|
||||||
|
XXXXX XX XX X XXXXXXXXXX XXXXXX XXXXXXXXXXX XXXXX X
|
||||||
|
XXXXX XX XX X XXXXXXXXXX XXXXXX XXXXXXXXXXX XXXXX X
|
||||||
|
XXXXX XX XX X XXXXXXXXXX XXXXXX XXXXXXXXXXX XXXXX X
|
||||||
|
XXXXX XX XXXX X XXXXXXXXXXXXXXXXX XXXX XXXXXXXXXXXXXXX XXXX X
|
||||||
|
|
||||||
|
XXXXXXXX
|
||||||
|
XXXXXXX
|
||||||
|
XXXXXX
|
||||||
|
|
||||||
|
XXXXXXXXXXXX XXXXXX XXXXX XXXXXXXXXXXXXX
|
||||||
|
|
||||||
|
XXXXXX XXXXXXXXXXXXX
|
||||||
|
XXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
|
||||||
|
XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||||
|
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||||
|
XXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||||
|
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X XX XXXX XXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXX
|
||||||
|
|
||||||
|
XXXXXXX XXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXX
|
||||||
|
XXXXXXXXXXXXXXXXXXXX X XXXX XXXX X XX XXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXX XXXXXXXX XXXXXXXXXXXXXXXXXXXXX
|
||||||
|
XXXXXXXXXXXXXXXXXXXXX XX XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXX XXXXXXXXXX XXXX XXXXXXXXXXXXXXXXXXXXXXXXXXX XXXX XXXXXXXX XXXXXXXXXXXXXXXXXXXXX
|
||||||
|
|
||||||
|
|
||||||
|
XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||||
|
XXXXXXXXXXXXXXXXXX XXXX XXXX XXX XXXX XXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXX
|
||||||
|
XXXXXXXXXXXXXXXXXXX XXXX XXXX XXXX XXXX XXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXX
|
||||||
|
|
||||||
|
XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||||
|
XXXXXXXXXXXXXXXXXX XXXXX X XXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
|
||||||
|
XXXXXXXXXXXXXXXXXXX XXXXX XXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
|
||||||
|
|
||||||
|
XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||||
|
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||||
|
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||||
|
XXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXX
|
||||||
|
XXXXXXXX
|
||||||
|
|
||||||
|
XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||||
|
XXXX XXXXXXXXX XX XXXXXXXX XXXXXXXXXXX
|
||||||
|
XXXX
|
||||||
|
|
||||||
|
XXXXXXX
|
||||||
|
XXXXXXX
|
|
@ -10,9 +10,6 @@ from .helpers import is_valid_domain, read_live_lineages, configure_cert
|
||||||
from .forms import LetsEncryptForm
|
from .forms import LetsEncryptForm
|
||||||
|
|
||||||
|
|
||||||
@admin.action(
|
|
||||||
description="Let's encrypt!"
|
|
||||||
)
|
|
||||||
def letsencrypt(modeladmin, request, queryset):
|
def letsencrypt(modeladmin, request, queryset):
|
||||||
wildcards = set()
|
wildcards = set()
|
||||||
domains = set()
|
domains = set()
|
||||||
|
@ -115,3 +112,4 @@ def letsencrypt(modeladmin, request, queryset):
|
||||||
'form': form,
|
'form': form,
|
||||||
}
|
}
|
||||||
return TemplateResponse(request, 'admin/orchestra/generic_confirmation.html', context)
|
return TemplateResponse(request, 'admin/orchestra/generic_confirmation.html', context)
|
||||||
|
letsencrypt.short_description = "Let's encrypt!"
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
default_app_config = 'orchestra.contrib.lists.apps.ListsConfig'
|
|
@ -16,7 +16,6 @@ from .filters import HasCustomAddressListFilter
|
||||||
from .models import List
|
from .models import List
|
||||||
|
|
||||||
|
|
||||||
@admin.register(List)
|
|
||||||
class ListAdmin(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'
|
||||||
|
@ -57,3 +56,4 @@ class ListAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
|
|
||||||
address_domain_link = admin_link('address_domain', order='address_domain__name')
|
address_domain_link = admin_link('address_domain', order='address_domain__name')
|
||||||
|
|
||||||
|
admin.site.register(List, ListAdmin)
|
||||||
|
|
|
@ -57,6 +57,14 @@ class MailmanVirtualDomainController(ServiceController):
|
||||||
def commit(self):
|
def commit(self):
|
||||||
context = self.get_context_files()
|
context = self.get_context_files()
|
||||||
super(MailmanVirtualDomainController, self).commit()
|
super(MailmanVirtualDomainController, self).commit()
|
||||||
|
self.append(textwrap.dedent("""
|
||||||
|
# Apply changes if needed
|
||||||
|
if [[ $UPDATED_VIRTUAL_ALIAS_DOMAINS == 1 ]]; then
|
||||||
|
postmap %(virtual_alias_domains)s
|
||||||
|
systemctl reload postfix
|
||||||
|
fi
|
||||||
|
exit $exit_code""") % context
|
||||||
|
)
|
||||||
|
|
||||||
def get_context_files(self):
|
def get_context_files(self):
|
||||||
return {
|
return {
|
||||||
|
@ -101,7 +109,7 @@ class MailmanController(MailmanVirtualDomainController):
|
||||||
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 virtual aliases
|
# Because mailman doesn't properly handle lists aliases we need virtual aliases
|
||||||
if context['address_name'] != context['name']:
|
if context['address_name'] != context['name'] or context['address_domain'] != settings.LISTS_DEFAULT_DOMAIN:
|
||||||
aliases.append("%(address_name)s%(suffix)s@%(domain)s\t%(name)s%(suffix)s@grups.pangea.org" % context)
|
aliases.append("%(address_name)s%(suffix)s@%(domain)s\t%(name)s%(suffix)s@grups.pangea.org" % context)
|
||||||
return '\n'.join(aliases)
|
return '\n'.join(aliases)
|
||||||
|
|
||||||
|
@ -165,7 +173,18 @@ class MailmanController(MailmanVirtualDomainController):
|
||||||
|
|
||||||
|
|
||||||
def commit(self):
|
def commit(self):
|
||||||
pass
|
context = self.get_context_files()
|
||||||
|
self.append(textwrap.dedent("""
|
||||||
|
# Apply changes if needed
|
||||||
|
if [[ $UPDATED_VIRTUAL_ALIAS == 1 ]]; then
|
||||||
|
postmap %(virtual_alias)s
|
||||||
|
fi
|
||||||
|
if [[ $UPDATED_VIRTUAL_ALIAS_DOMAINS == 1 ]]; then
|
||||||
|
systemctl reload postfix
|
||||||
|
fi
|
||||||
|
exit $exit_code""") % context
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_context_files(self):
|
def get_context_files(self):
|
||||||
return {
|
return {
|
||||||
|
@ -199,7 +218,7 @@ class MailmanTraffic(ServiceMonitor):
|
||||||
model = 'lists.List'
|
model = 'lists.List'
|
||||||
resource = ServiceMonitor.TRAFFIC
|
resource = ServiceMonitor.TRAFFIC
|
||||||
verbose_name = _("Mailman traffic")
|
verbose_name = _("Mailman traffic")
|
||||||
script_executable = '/usr/bin/python'
|
script_executable = '/usr/bin/python3'
|
||||||
monthly_sum_old_values = True
|
monthly_sum_old_values = True
|
||||||
doc_settings = (settings,
|
doc_settings = (settings,
|
||||||
('LISTS_MAILMAN_POST_LOG_PATH',)
|
('LISTS_MAILMAN_POST_LOG_PATH',)
|
||||||
|
@ -210,9 +229,10 @@ class MailmanTraffic(ServiceMonitor):
|
||||||
context = {
|
context = {
|
||||||
'postlogs': str((postlog, postlog+'.1')),
|
'postlogs': str((postlog, postlog+'.1')),
|
||||||
'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"),
|
||||||
|
'default_domain': settings.LISTS_DEFAULT_DOMAIN,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.append(textwrap.dedent("""\
|
self.append(textwrap.dedent("""\
|
||||||
import re
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
@ -243,7 +263,6 @@ class MailmanTraffic(ServiceMonitor):
|
||||||
'Nov': '11',
|
'Nov': '11',
|
||||||
'Dec': '12',
|
'Dec': '12',
|
||||||
}}
|
}}
|
||||||
mailman_addr = re.compile(r'.*-(admin|bounces|confirm|join|leave|owner|request|subscribe|unsubscribe)@.*|mailman@.*')
|
|
||||||
|
|
||||||
def prepare(object_id, list_name, ini_date):
|
def prepare(object_id, list_name, ini_date):
|
||||||
global lists
|
global lists
|
||||||
|
@ -255,39 +274,33 @@ class MailmanTraffic(ServiceMonitor):
|
||||||
for postlog in postlogs:
|
for postlog in postlogs:
|
||||||
try:
|
try:
|
||||||
with open(postlog, 'r') as postlog:
|
with open(postlog, 'r') as postlog:
|
||||||
|
recps_dict = {{}}
|
||||||
for line in postlog.readlines():
|
for line in postlog.readlines():
|
||||||
line = line.split()
|
line = line.split()
|
||||||
if len(line) < 11:
|
if 'recips,' in line:
|
||||||
|
__, __, __, __, __, id, __, __, list_name, __, recps = line[:11]
|
||||||
|
recps_dict[id] = recps
|
||||||
continue
|
continue
|
||||||
month, day, time, year, __, __, __, list_name, __, addr, size = line[:11]
|
if not 'bytes' in line:
|
||||||
|
continue
|
||||||
|
month, day, time, year, __, __, __, __, list_name, __, addr, size = line[:12]
|
||||||
try:
|
try:
|
||||||
|
list_name = list_name.split('@')[0]
|
||||||
list = lists[list_name]
|
list = lists[list_name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
# discard mailman messages because of inconsistent POST logging
|
|
||||||
if mailman_addr.match(addr):
|
|
||||||
continue
|
|
||||||
date = year + months[month] + day + time.replace(':', '')
|
date = year + months[month] + day + time.replace(':', '')
|
||||||
if list[0] < int(date) < end_date:
|
if list[0] < int(date) < end_date:
|
||||||
size = size[5:-1]
|
if id in recps_dict:
|
||||||
try:
|
list[2] += int(size) * int(recps_dict[id])
|
||||||
list[2] += int(size)
|
|
||||||
except ValueError:
|
|
||||||
# anonymized post
|
|
||||||
pass
|
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
sys.stderr.write(str(e)+'\\n')
|
sys.stderr.write(str(e)+'\\n')
|
||||||
|
|
||||||
for list_name, opts in lists.items():
|
for list_name, opts in lists.items():
|
||||||
__, object_id, size = opts
|
__, object_id, size = opts
|
||||||
if size:
|
print(object_id, size)
|
||||||
cmd = ' '.join(('list_members', list_name, '| wc -l'))
|
|
||||||
ps = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
||||||
subscribers = ps.communicate()[0].strip()
|
|
||||||
size *= int(subscribers)
|
|
||||||
sys.stderr.write("%s %s*%s traffic*subscribers\\n" % (object_id, size, subscribers))
|
|
||||||
print object_id, size
|
|
||||||
""").format(**context)
|
""").format(**context)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,117 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-06 10:23+0000\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
#: admin.py:28 admin.py:42
|
||||||
|
msgid "Address"
|
||||||
|
msgstr "Direccio"
|
||||||
|
|
||||||
|
#: admin.py:32
|
||||||
|
msgid "Admin"
|
||||||
|
msgstr "Administrador"
|
||||||
|
|
||||||
|
#: admin.py:44
|
||||||
|
#, python-format
|
||||||
|
msgid "Additional address besides the default <name>@%s"
|
||||||
|
msgstr "Adreça addicional a més del valor predeterminat <name>@%s"
|
||||||
|
|
||||||
|
#: backends.py:16
|
||||||
|
msgid "Mailman virtdomain-only"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: backends.py:201
|
||||||
|
msgid "Mailman traffic"
|
||||||
|
msgstr "Trànsit de Mailman"
|
||||||
|
|
||||||
|
#: backends.py:309
|
||||||
|
msgid "Mailman subscribers"
|
||||||
|
msgstr "Subscriptors Mailman"
|
||||||
|
|
||||||
|
#: filters.py:7
|
||||||
|
msgid "has custom address"
|
||||||
|
msgstr "té adreça personalitzada"
|
||||||
|
|
||||||
|
#: filters.py:12
|
||||||
|
msgid "True"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: filters.py:13
|
||||||
|
msgid "False"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:13
|
||||||
|
msgid "name"
|
||||||
|
msgstr "nom"
|
||||||
|
|
||||||
|
#: models.py:14
|
||||||
|
#, python-format
|
||||||
|
msgid "Default list address <name>@%s"
|
||||||
|
msgstr "Adreça de llista predeterminada <name>@%s"
|
||||||
|
|
||||||
|
#: models.py:15
|
||||||
|
msgid "address name"
|
||||||
|
msgstr "Nom de l'adreça"
|
||||||
|
|
||||||
|
#: models.py:18
|
||||||
|
msgid "address domain"
|
||||||
|
msgstr "Domini adicional"
|
||||||
|
|
||||||
|
#: models.py:19
|
||||||
|
msgid "admin email"
|
||||||
|
msgstr "Correu electrònic d'administració"
|
||||||
|
|
||||||
|
#: models.py:20
|
||||||
|
msgid "Administration email address"
|
||||||
|
msgstr "Adreça de correu electrònic d'administració"
|
||||||
|
|
||||||
|
#: models.py:21
|
||||||
|
msgid "Account"
|
||||||
|
msgstr "Compte"
|
||||||
|
|
||||||
|
#: models.py:24
|
||||||
|
msgid "active"
|
||||||
|
msgstr "actiu"
|
||||||
|
|
||||||
|
#: models.py:25
|
||||||
|
msgid ""
|
||||||
|
"Designates whether this account should be treated as active. Unselect this "
|
||||||
|
"instead of deleting accounts."
|
||||||
|
msgstr ""
|
||||||
|
"Designa si aquest compte ha de ser tractat com a actiu. Deselecteu això "
|
||||||
|
"En lloc de suprimir els comptes."
|
||||||
|
|
||||||
|
#: models.py:47
|
||||||
|
msgid "Domain should be selected for provided address name."
|
||||||
|
msgstr "El domini s'ha de seleccionar per al nom de l'adreça proporcionat."
|
||||||
|
|
||||||
|
#: serializers.py:20
|
||||||
|
msgid "Password"
|
||||||
|
msgstr "Contrasenya"
|
||||||
|
|
||||||
|
#: serializers.py:25
|
||||||
|
msgid ""
|
||||||
|
"Enter a valid password. This value may contain any ascii character except "
|
||||||
|
"for '/\"/\\/ characters."
|
||||||
|
msgstr ""
|
||||||
|
"Introduïu una contrasenya vàlida. Aquest valor pot contenir qualsevol personatge ASCII excepte"
|
||||||
|
"Per a '/\"/\\/caràcters. "
|
||||||
|
|
||||||
|
#: serializers.py:43
|
||||||
|
msgid "address_domains should should be provided when providing an addres_name"
|
||||||
|
msgstr "S'hauria de proporcionar address_domains en proporcionar un address_name"
|
Binary file not shown.
|
@ -0,0 +1,117 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-06 10:03+0000\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
#: admin.py:28 admin.py:42
|
||||||
|
msgid "Address"
|
||||||
|
msgstr "Dirección"
|
||||||
|
|
||||||
|
#: admin.py:32
|
||||||
|
msgid "Admin"
|
||||||
|
msgstr "Administrador"
|
||||||
|
|
||||||
|
#: admin.py:44
|
||||||
|
#, python-format
|
||||||
|
msgid "Additional address besides the default <name>@%s"
|
||||||
|
msgstr "Dirección adicional además del valor predeterminado <name>@%s"
|
||||||
|
|
||||||
|
#: backends.py:16
|
||||||
|
msgid "Mailman virtdomain-only"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: backends.py:201
|
||||||
|
msgid "Mailman traffic"
|
||||||
|
msgstr "Tráfico Mailman"
|
||||||
|
|
||||||
|
#: backends.py:309
|
||||||
|
msgid "Mailman subscribers"
|
||||||
|
msgstr "Subscriptores Mailman"
|
||||||
|
|
||||||
|
#: filters.py:7
|
||||||
|
msgid "has custom address"
|
||||||
|
msgstr "tiene dirección personalizada"
|
||||||
|
|
||||||
|
#: filters.py:12
|
||||||
|
msgid "True"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: filters.py:13
|
||||||
|
msgid "False"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:13
|
||||||
|
msgid "name"
|
||||||
|
msgstr "nombre"
|
||||||
|
|
||||||
|
#: models.py:14
|
||||||
|
#, python-format
|
||||||
|
msgid "Default list address <name>@%s"
|
||||||
|
msgstr "dirección de lista por defecto <name>@%s"
|
||||||
|
|
||||||
|
#: models.py:15
|
||||||
|
msgid "address name"
|
||||||
|
msgstr "nombre de dirección"
|
||||||
|
|
||||||
|
#: models.py:18
|
||||||
|
msgid "address domain"
|
||||||
|
msgstr "dominio adicional"
|
||||||
|
|
||||||
|
#: models.py:19
|
||||||
|
msgid "admin email"
|
||||||
|
msgstr "correo administrador"
|
||||||
|
|
||||||
|
#: models.py:20
|
||||||
|
msgid "Administration email address"
|
||||||
|
msgstr "dirección correo administrador"
|
||||||
|
|
||||||
|
#: models.py:21
|
||||||
|
msgid "Account"
|
||||||
|
msgstr "Cuenta"
|
||||||
|
|
||||||
|
#: models.py:24
|
||||||
|
msgid "active"
|
||||||
|
msgstr "activo"
|
||||||
|
|
||||||
|
#: models.py:25
|
||||||
|
msgid ""
|
||||||
|
"Designates whether this account should be treated as active. Unselect this "
|
||||||
|
"instead of deleting accounts."
|
||||||
|
msgstr ""
|
||||||
|
"Designa si esta cuenta debe tratarse como activa. Deseleccionar esto "
|
||||||
|
"En lugar de eliminar cuentas."
|
||||||
|
|
||||||
|
#: models.py:47
|
||||||
|
msgid "Domain should be selected for provided address name."
|
||||||
|
msgstr "El dominio debe seleccionarse para el nombre de la dirección proporcionado."
|
||||||
|
|
||||||
|
#: serializers.py:20
|
||||||
|
msgid "Password"
|
||||||
|
msgstr "Contraseña"
|
||||||
|
|
||||||
|
#: serializers.py:25
|
||||||
|
msgid ""
|
||||||
|
"Enter a valid password. This value may contain any ascii character except "
|
||||||
|
"for '/\"/\\/ characters."
|
||||||
|
msgstr ""
|
||||||
|
"Ingrese una contraseña válida. Este valor puede contener cualquier carácter ASCII excepto"
|
||||||
|
"Para '/\"/\\/caracteres."
|
||||||
|
|
||||||
|
#: serializers.py:43
|
||||||
|
msgid "address_domains should should be provided when providing an addres_name"
|
||||||
|
msgstr "address_domains debe proporcionarse al proporcionar un addres_name"
|
|
@ -1,4 +1,6 @@
|
||||||
# Generated by Django 2.2.28 on 2023-09-01 14:59
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.5 on 2021-04-22 11:27
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -8,10 +10,8 @@ import orchestra.core.validators
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
initial = True
|
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('domains', '__first__'),
|
('domains', '0001_initial'),
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -20,15 +20,46 @@ class Migration(migrations.Migration):
|
||||||
name='List',
|
name='List',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('name', models.CharField(help_text='Default list address <name>@grups.pangea.org', max_length=64, unique=True, validators=[orchestra.core.validators.validate_name], verbose_name='name')),
|
('name', models.CharField(help_text='Default list address <name>@lists.orchestra.lan', max_length=128, 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')),
|
('address_name', models.CharField(blank=True, max_length=128, 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')),
|
('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')),
|
('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(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='domains.Domain', verbose_name='address domain')),
|
('address_domain', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='domains.Domain', verbose_name='address domain')),
|
||||||
],
|
],
|
||||||
options={
|
),
|
||||||
'unique_together': {('address_name', 'address_domain')},
|
migrations.AlterUniqueTogether(
|
||||||
},
|
name='list',
|
||||||
|
unique_together=set([('address_name', 'address_domain')]),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='list',
|
||||||
|
name='address_domain',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='domains.Domain', verbose_name='address domain'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='list',
|
||||||
|
name='address_name',
|
||||||
|
field=models.CharField(blank=True, max_length=52, validators=[orchestra.core.validators.validate_name], verbose_name='address name'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='list',
|
||||||
|
name='name',
|
||||||
|
field=models.CharField(help_text='Default list address <name>@grups.pangea.org', max_length=52, unique=True, validators=[orchestra.core.validators.validate_name], verbose_name='name'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='list',
|
||||||
|
name='address_name',
|
||||||
|
field=models.CharField(blank=True, max_length=64, validators=[orchestra.core.validators.validate_name], verbose_name='address name'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='list',
|
||||||
|
name='name',
|
||||||
|
field=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'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='list',
|
||||||
|
name='name',
|
||||||
|
field=models.CharField(help_text='Default list address <name>@lists.orchestra.lan', max_length=64, unique=True, validators=[orchestra.core.validators.validate_name], verbose_name='name'),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.10.5 on 2021-04-22 11:27
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
import orchestra.core.validators
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
replaces = [('lists', '0001_initial'), ('lists', '0002_auto_20160912_1221'), ('lists', '0003_auto_20160912_1241'), ('lists', '0004_auto_20210330_1049')]
|
|
||||||
|
|
||||||
initial = True
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('domains', '0001_initial'),
|
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='List',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('name', models.CharField(help_text='Default list address <name>@lists.orchestra.lan', max_length=128, unique=True, validators=[orchestra.core.validators.validate_name], verbose_name='name')),
|
|
||||||
('address_name', models.CharField(blank=True, max_length=128, 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(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='domains.Domain', verbose_name='address domain')),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.AlterUniqueTogether(
|
|
||||||
name='list',
|
|
||||||
unique_together=set([('address_name', 'address_domain')]),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='list',
|
|
||||||
name='address_domain',
|
|
||||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='domains.Domain', verbose_name='address domain'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='list',
|
|
||||||
name='address_name',
|
|
||||||
field=models.CharField(blank=True, max_length=52, validators=[orchestra.core.validators.validate_name], verbose_name='address name'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='list',
|
|
||||||
name='name',
|
|
||||||
field=models.CharField(help_text='Default list address <name>@grups.pangea.org', max_length=52, unique=True, validators=[orchestra.core.validators.validate_name], verbose_name='name'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='list',
|
|
||||||
name='address_name',
|
|
||||||
field=models.CharField(blank=True, max_length=64, validators=[orchestra.core.validators.validate_name], verbose_name='address name'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='list',
|
|
||||||
name='name',
|
|
||||||
field=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'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='list',
|
|
||||||
name='name',
|
|
||||||
field=models.CharField(help_text='Default list address <name>@lists.orchestra.lan', max_length=64, unique=True, validators=[orchestra.core.validators.validate_name], verbose_name='name'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,32 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.9.5 on 2016-09-12 10:21
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
import orchestra.core.validators
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('lists', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='list',
|
|
||||||
name='address_domain',
|
|
||||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='domains.Domain', verbose_name='address domain'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='list',
|
|
||||||
name='address_name',
|
|
||||||
field=models.CharField(blank=True, max_length=52, validators=[orchestra.core.validators.validate_name], verbose_name='address name'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='list',
|
|
||||||
name='name',
|
|
||||||
field=models.CharField(help_text='Default list address <name>@grups.pangea.org', max_length=52, unique=True, validators=[orchestra.core.validators.validate_name], verbose_name='name'),
|
|
||||||
),
|
|
||||||
]
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue