Dont delete lists when deleting domains
This commit is contained in:
parent
27aec2e5f0
commit
682a8947d3
9
TODO.md
9
TODO.md
|
@ -443,21 +443,12 @@ mkhomedir_helper or create ssh homes with bash.rc and such
|
||||||
# Reversion
|
# Reversion
|
||||||
# Disable/enable SaaS and VPS
|
# Disable/enable SaaS and VPS
|
||||||
|
|
||||||
# AGO
|
|
||||||
|
|
||||||
# Don't show lines with size 0?
|
# Don't show lines with size 0?
|
||||||
# pending orders with recharge do not show up
|
# pending orders with recharge do not show up
|
||||||
# Traffic of disabled accounts doesn't get disabled
|
# Traffic of disabled accounts doesn't get disabled
|
||||||
|
|
||||||
# is_active list filter account dissabled filtering support
|
|
||||||
|
|
||||||
# URL encode "Order description" on clone
|
# URL encode "Order description" on clone
|
||||||
# Service CLONE METRIC doesn't work
|
# Service CLONE METRIC doesn't work
|
||||||
|
|
||||||
|
|
||||||
# Show warning when saving order and metricstorage date is inconistent with registered date!
|
# Show warning when saving order and metricstorage date is inconistent with registered date!
|
||||||
|
|
||||||
# Warn user if changes are not saved
|
|
||||||
|
|
||||||
# exclude from change list action, support for multiple exclusion
|
# exclude from change list action, support for multiple exclusion
|
||||||
# support for better edditing bill lines and sublines
|
|
||||||
|
|
|
@ -92,7 +92,10 @@ def action_to_view(action, modeladmin):
|
||||||
|
|
||||||
def change_url(obj):
|
def change_url(obj):
|
||||||
if obj is not None:
|
if obj is not None:
|
||||||
|
cls = type(obj)
|
||||||
opts = obj._meta
|
opts = obj._meta
|
||||||
|
if cls._deferred:
|
||||||
|
opts = cls.__base__._meta
|
||||||
view_name = 'admin:%s_%s_change' % (opts.app_label, opts.model_name)
|
view_name = 'admin:%s_%s_change' % (opts.app_label, opts.model_name)
|
||||||
return reverse(view_name, args=(obj.pk,))
|
return reverse(view_name, args=(obj.pk,))
|
||||||
raise NoReverseMatch
|
raise NoReverseMatch
|
||||||
|
|
|
@ -12,6 +12,8 @@ class HasMainUserListFilter(SimpleListFilter):
|
||||||
return (
|
return (
|
||||||
('True', _("Yes")),
|
('True', _("Yes")),
|
||||||
('False', _("No")),
|
('False', _("No")),
|
||||||
|
('account', _("Account disabled")),
|
||||||
|
('object', _("Object disabled")),
|
||||||
)
|
)
|
||||||
|
|
||||||
def queryset(self, request, queryset):
|
def queryset(self, request, queryset):
|
||||||
|
@ -30,4 +32,8 @@ class IsActiveListFilter(HasMainUserListFilter):
|
||||||
return queryset.filter(is_active=True, account__is_active=True)
|
return queryset.filter(is_active=True, account__is_active=True)
|
||||||
elif self.value() == 'False':
|
elif self.value() == 'False':
|
||||||
return queryset.filter(Q(is_active=False) | Q(account__is_active=False))
|
return queryset.filter(Q(is_active=False) | Q(account__is_active=False))
|
||||||
|
elif self.value() == 'account':
|
||||||
|
return queryset.filter(account__is_active=False)
|
||||||
|
elif self.value() == 'object':
|
||||||
|
return queryset.filter(is_active=False)
|
||||||
return queryset
|
return queryset
|
||||||
|
|
|
@ -289,7 +289,9 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
'closed_on_display', 'updated_on_display', 'display_total_with_subtotals',
|
'closed_on_display', 'updated_on_display', 'display_total_with_subtotals',
|
||||||
)
|
)
|
||||||
inlines = [BillLineInline, ClosedBillLineInline]
|
inlines = [BillLineInline, ClosedBillLineInline]
|
||||||
#date_hierarchy = 'closed_on'
|
date_hierarchy = 'closed_on'
|
||||||
|
# TODO when merged https://github.com/django/django/pull/5213
|
||||||
|
#approximate_date_hierarchy = admin.ApproximateWith.MONTHS
|
||||||
|
|
||||||
created_on_display = admin_date('created_on', short_description=_("Created"))
|
created_on_display = admin_date('created_on', short_description=_("Created"))
|
||||||
closed_on_display = admin_date('closed_on', short_description=_("Closed"))
|
closed_on_display = admin_date('closed_on', short_description=_("Closed"))
|
||||||
|
@ -426,7 +428,7 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
qs = qs.prefetch_related(
|
qs = qs.prefetch_related(
|
||||||
Prefetch('amends', queryset=Bill.objects.filter(is_open=False), to_attr='closed_amends')
|
Prefetch('amends', queryset=Bill.objects.filter(is_open=False), to_attr='closed_amends')
|
||||||
)
|
)
|
||||||
return qs
|
return qs.defer('html')
|
||||||
|
|
||||||
def change_view(self, request, object_id, **kwargs):
|
def change_view(self, request, object_id, **kwargs):
|
||||||
# TODO raise404, here and everywhere
|
# TODO raise404, here and everywhere
|
||||||
|
|
|
@ -123,6 +123,8 @@ class Bill(models.Model):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_class_type(cls):
|
def get_class_type(cls):
|
||||||
|
if cls._deferred:
|
||||||
|
cls = cls.__base__
|
||||||
return cls.__name__.upper()
|
return cls.__name__.upper()
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
|
@ -212,6 +214,10 @@ class Bill(models.Model):
|
||||||
def get_type(self):
|
def get_type(self):
|
||||||
return self.type or self.get_class_type()
|
return self.type or self.get_class_type()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_amend(self):
|
||||||
|
return self.type in self.AMEND_MAP.values()
|
||||||
|
|
||||||
def get_amend_type(self):
|
def get_amend_type(self):
|
||||||
amend_type = self.AMEND_MAP.get(self.type)
|
amend_type = self.AMEND_MAP.get(self.type)
|
||||||
if amend_type is None:
|
if amend_type is None:
|
||||||
|
@ -220,6 +226,8 @@ class Bill(models.Model):
|
||||||
|
|
||||||
def get_number(self):
|
def get_number(self):
|
||||||
cls = type(self)
|
cls = type(self)
|
||||||
|
if cls._deferred:
|
||||||
|
cls = cls.__base__
|
||||||
bill_type = self.get_type()
|
bill_type = self.get_type()
|
||||||
if bill_type == self.BILL:
|
if bill_type == self.BILL:
|
||||||
raise TypeError('This method can not be used on BILL instances')
|
raise TypeError('This method can not be used on BILL instances')
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
|
|
||||||
<table id="summary">
|
<table id="summary">
|
||||||
<tr class="header">
|
<tr class="header">
|
||||||
<th class="title column-name">{% trans "Services" %}</th>
|
<th class="title column-name">{% trans "Service" %}</th>
|
||||||
<th class="title column-active">{% trans "Active" %}</th>
|
<th class="title column-active">{% trans "Active" %}</th>
|
||||||
<th class="title column-cancelled">{% trans "Cancelled" %}</th>
|
<th class="title column-cancelled">{% trans "Cancelled" %}</th>
|
||||||
<th class="title column-nominal-price">{% trans "Nominal price" %}</th>
|
<th class="title column-nominal-price">{% trans "Nominal price" %}</th>
|
||||||
|
|
|
@ -9,10 +9,10 @@ from orchestra.admin.utils import admin_link
|
||||||
from orchestra.contrib.accounts.actions import list_accounts
|
from orchestra.contrib.accounts.actions import list_accounts
|
||||||
from orchestra.contrib.accounts.admin import SelectAccountAdminMixin
|
from orchestra.contrib.accounts.admin import SelectAccountAdminMixin
|
||||||
from orchestra.contrib.accounts.filters import IsActiveListFilter
|
from orchestra.contrib.accounts.filters import IsActiveListFilter
|
||||||
|
from orchestra.forms import UserCreationForm, NonStoredUserChangeForm
|
||||||
|
|
||||||
from . import settings
|
from . import settings
|
||||||
from .filters import HasCustomAddressListFilter
|
from .filters import HasCustomAddressListFilter
|
||||||
from .forms import ListCreationForm, ListChangeForm
|
|
||||||
from .models import List
|
from .models import List
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,8 +54,8 @@ class ListAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedModel
|
||||||
list_filter = (IsActiveListFilter, HasCustomAddressListFilter)
|
list_filter = (IsActiveListFilter, HasCustomAddressListFilter)
|
||||||
readonly_fields = ('account_link',)
|
readonly_fields = ('account_link',)
|
||||||
change_readonly_fields = ('name',)
|
change_readonly_fields = ('name',)
|
||||||
form = ListChangeForm
|
form = NonStoredUserChangeForm
|
||||||
add_form = ListCreationForm
|
add_form = UserCreationForm
|
||||||
list_select_related = ('account', 'address_domain',)
|
list_select_related = ('account', 'address_domain',)
|
||||||
filter_by_account_fields = ['address_domain']
|
filter_by_account_fields = ['address_domain']
|
||||||
actions = (disable, enable, list_accounts)
|
actions = (disable, enable, list_accounts)
|
||||||
|
|
|
@ -10,3 +10,4 @@ class ListsConfig(AppConfig):
|
||||||
def ready(self):
|
def ready(self):
|
||||||
from .models import List
|
from .models import List
|
||||||
services.register(List, icon='email-alter.png')
|
services.register(List, icon='email-alter.png')
|
||||||
|
from . import signals
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
from orchestra.forms import UserCreationForm, NonStoredUserChangeForm
|
|
||||||
|
|
||||||
|
|
||||||
class CleanAddressMixin(object):
|
|
||||||
def clean_address_domain(self):
|
|
||||||
name = self.cleaned_data.get('address_name')
|
|
||||||
domain = self.cleaned_data.get('address_domain')
|
|
||||||
if name and not domain:
|
|
||||||
msg = _("Domain should be selected for provided address name")
|
|
||||||
raise forms.ValidationError(msg)
|
|
||||||
return domain
|
|
||||||
|
|
||||||
|
|
||||||
class ListCreationForm(CleanAddressMixin, UserCreationForm):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class ListChangeForm(CleanAddressMixin, NonStoredUserChangeForm):
|
|
||||||
pass
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
@ -25,7 +26,7 @@ class List(models.Model):
|
||||||
help_text=_("Default list address <name>@%s") % settings.LISTS_DEFAULT_DOMAIN)
|
help_text=_("Default list address <name>@%s") % settings.LISTS_DEFAULT_DOMAIN)
|
||||||
address_name = models.CharField(_("address name"), max_length=128,
|
address_name = models.CharField(_("address name"), max_length=128,
|
||||||
validators=[validate_name], blank=True)
|
validators=[validate_name], blank=True)
|
||||||
address_domain = models.ForeignKey(settings.LISTS_DOMAIN_MODEL,
|
address_domain = models.ForeignKey(settings.LISTS_DOMAIN_MODEL, on_delete=models.SET_NULL,
|
||||||
verbose_name=_("address domain"), blank=True, null=True)
|
verbose_name=_("address domain"), blank=True, null=True)
|
||||||
admin_email = models.EmailField(_("admin email"),
|
admin_email = models.EmailField(_("admin email"),
|
||||||
help_text=_("Administration email address"))
|
help_text=_("Administration email address"))
|
||||||
|
@ -55,6 +56,12 @@ class List(models.Model):
|
||||||
def active(self):
|
def active(self):
|
||||||
return self.is_active and self.account.is_active
|
return self.is_active and self.account.is_active
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
if self.address_name and not self.address_domain_id:
|
||||||
|
raise ValidationError({
|
||||||
|
'address_domain': _("Domain should be selected for provided address name."),
|
||||||
|
})
|
||||||
|
|
||||||
def disable(self):
|
def disable(self):
|
||||||
self.is_active = False
|
self.is_active = False
|
||||||
self.save(update_fields=('is_active',))
|
self.save(update_fields=('is_active',))
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
from django.apps import apps
|
||||||
|
from django.db.models.signals import pre_delete
|
||||||
|
from django.dispatch import receiver
|
||||||
|
|
||||||
|
from . import settings
|
||||||
|
from .models import List
|
||||||
|
|
||||||
|
|
||||||
|
DOMAIN_MODEL = apps.get_model(settings.LISTS_DOMAIN_MODEL)
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(pre_delete, sender=DOMAIN_MODEL, dispatch_uid="lists.clean_address_name")
|
||||||
|
def clean_address_name(sender, **kwargs):
|
||||||
|
domain = kwargs['instance']
|
||||||
|
for list in List.objects.filter(address_domain_id=domain.pk):
|
||||||
|
list.address_name = ''
|
||||||
|
list.address_domain_id = None
|
||||||
|
list.save(update_fields=('address_name', 'address_domain_id'))
|
||||||
|
|
|
@ -22,6 +22,13 @@ STATE_COLORS = {
|
||||||
Transaction.REJECTED: 'red',
|
Transaction.REJECTED: 'red',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PROCESS_STATE_COLORS = {
|
||||||
|
TransactionProcess.CREATED: 'blue',
|
||||||
|
TransactionProcess.EXECUTED: 'olive',
|
||||||
|
TransactionProcess.ABORTED: 'red',
|
||||||
|
TransactionProcess.COMMITED: 'green',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class PaymentSourceAdmin(SelectPluginAdminMixin, AccountAdminMixin, admin.ModelAdmin):
|
class PaymentSourceAdmin(SelectPluginAdminMixin, AccountAdminMixin, admin.ModelAdmin):
|
||||||
list_display = ('label', 'method', 'number', 'account_link', 'is_active')
|
list_display = ('label', 'method', 'number', 'account_link', 'is_active')
|
||||||
|
@ -61,8 +68,8 @@ class TransactionInline(admin.TabularInline):
|
||||||
|
|
||||||
class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
list_display = (
|
list_display = (
|
||||||
'id', 'bill_link', 'account_link', 'source_link', 'display_created_at', 'display_modified_at', 'display_state',
|
'id', 'bill_link', 'account_link', 'source_link', 'display_created_at',
|
||||||
'amount', 'process_link'
|
'display_modified_at', 'display_state', 'amount', 'process_link'
|
||||||
)
|
)
|
||||||
list_filter = ('source__method', 'state')
|
list_filter = ('source__method', 'state')
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
|
@ -142,7 +149,10 @@ class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
|
|
||||||
|
|
||||||
class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
|
class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
|
||||||
list_display = ('id', 'file_url', 'display_transactions', 'display_created_at')
|
list_display = (
|
||||||
|
'id', 'file_url', 'display_transactions', 'display_state', 'display_created_at',
|
||||||
|
)
|
||||||
|
list_filter = ('state',)
|
||||||
fields = ('data', 'file_url', 'created_at')
|
fields = ('data', 'file_url', 'created_at')
|
||||||
readonly_fields = ('data', 'file_url', 'display_transactions', 'created_at')
|
readonly_fields = ('data', 'file_url', 'display_transactions', 'created_at')
|
||||||
list_prefetch_related = ('transactions',)
|
list_prefetch_related = ('transactions',)
|
||||||
|
@ -152,6 +162,7 @@ class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
|
||||||
)
|
)
|
||||||
actions = change_view_actions + (actions.delete_selected,)
|
actions = change_view_actions + (actions.delete_selected,)
|
||||||
|
|
||||||
|
display_state = admin_colored('state', colors=PROCESS_STATE_COLORS)
|
||||||
display_created_at = admin_date('created_at', short_description=_("Created"))
|
display_created_at = admin_date('created_at', short_description=_("Created"))
|
||||||
|
|
||||||
def file_url(self, process):
|
def file_url(self, process):
|
||||||
|
@ -169,7 +180,7 @@ class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
|
||||||
state = trans.get_state_display()
|
state = trans.get_state_display()
|
||||||
ids.append('<span style="color:%s" title="%s">%i</span>' % (color, state, trans.id))
|
ids.append('<span style="color:%s" title="%s">%i</span>' % (color, state, trans.id))
|
||||||
counter += 1 + len(str(trans.id))
|
counter += 1 + len(str(trans.id))
|
||||||
if counter > 125:
|
if counter > 100:
|
||||||
counter = 0
|
counter = 0
|
||||||
lines.append(','.join(ids))
|
lines.append(','.join(ids))
|
||||||
ids = []
|
ids = []
|
||||||
|
|
|
@ -13,7 +13,7 @@ from .. import settings
|
||||||
class PaymentMethod(plugins.Plugin, metaclass=plugins.PluginMount):
|
class PaymentMethod(plugins.Plugin, metaclass=plugins.PluginMount):
|
||||||
label_field = 'label'
|
label_field = 'label'
|
||||||
number_field = 'number'
|
number_field = 'number'
|
||||||
process_credit = False
|
allow_recharge = False
|
||||||
due_delta = relativedelta.relativedelta(months=1)
|
due_delta = relativedelta.relativedelta(months=1)
|
||||||
plugin_field = 'method'
|
plugin_field = 'method'
|
||||||
state_help = {}
|
state_help = {}
|
||||||
|
|
|
@ -45,7 +45,7 @@ class SEPADirectDebit(PaymentMethod):
|
||||||
verbose_name = _("SEPA Direct Debit")
|
verbose_name = _("SEPA Direct Debit")
|
||||||
label_field = 'name'
|
label_field = 'name'
|
||||||
number_field = 'iban'
|
number_field = 'iban'
|
||||||
process_credit = True
|
allow_recharge = True
|
||||||
form = SEPADirectDebitForm
|
form = SEPADirectDebitForm
|
||||||
serializer = SEPADirectDebitSerializer
|
serializer = SEPADirectDebitSerializer
|
||||||
due_delta = datetime.timedelta(days=5)
|
due_delta = datetime.timedelta(days=5)
|
||||||
|
@ -96,7 +96,7 @@ class SEPADirectDebit(PaymentMethod):
|
||||||
)
|
)
|
||||||
sepa = sepa.Document(
|
sepa = sepa.Document(
|
||||||
E.CstmrCdtTrfInitn(
|
E.CstmrCdtTrfInitn(
|
||||||
cls.get_header(context),
|
cls.get_header(context, process),
|
||||||
E.PmtInf( # Payment Info
|
E.PmtInf( # Payment Info
|
||||||
E.PmtInfId(str(process.id)), # Payment Id
|
E.PmtInfId(str(process.id)), # Payment Id
|
||||||
E.PmtMtd("TRF"), # Payment Method
|
E.PmtMtd("TRF"), # Payment Method
|
||||||
|
@ -239,7 +239,7 @@ class SEPADirectDebit(PaymentMethod):
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_credit_transactions(transactions, process):
|
def get_credit_transactions(cls, transactions, process):
|
||||||
import lxml.builder
|
import lxml.builder
|
||||||
from lxml.builder import E
|
from lxml.builder import E
|
||||||
for transaction in transactions:
|
for transaction in transactions:
|
||||||
|
|
|
@ -7,6 +7,7 @@ from orchestra.admin.actions import disable, enable
|
||||||
from orchestra.admin.utils import change_url
|
from orchestra.admin.utils import change_url
|
||||||
from orchestra.contrib.accounts.actions import list_accounts
|
from orchestra.contrib.accounts.actions import list_accounts
|
||||||
from orchestra.contrib.accounts.admin import AccountAdminMixin
|
from orchestra.contrib.accounts.admin import AccountAdminMixin
|
||||||
|
from orchestra.contrib.accounts.filters import IsActiveListFilter
|
||||||
from orchestra.plugins.admin import SelectPluginAdminMixin
|
from orchestra.plugins.admin import SelectPluginAdminMixin
|
||||||
from orchestra.utils.apps import isinstalled
|
from orchestra.utils.apps import isinstalled
|
||||||
from orchestra.utils.html import get_on_site_link
|
from orchestra.utils.html import get_on_site_link
|
||||||
|
@ -17,8 +18,8 @@ from .services import SoftwareService
|
||||||
|
|
||||||
|
|
||||||
class SaaSAdmin(SelectPluginAdminMixin, ChangePasswordAdminMixin, AccountAdminMixin, ExtendedModelAdmin):
|
class SaaSAdmin(SelectPluginAdminMixin, ChangePasswordAdminMixin, AccountAdminMixin, ExtendedModelAdmin):
|
||||||
list_display = ('name', 'service', 'display_url', 'account_link', 'is_active')
|
list_display = ('name', 'service', 'display_url', 'account_link', 'display_active')
|
||||||
list_filter = ('service', 'is_active', CustomURLListFilter)
|
list_filter = ('service', IsActiveListFilter, CustomURLListFilter)
|
||||||
search_fields = ('name', 'account__username')
|
search_fields = ('name', 'account__username')
|
||||||
change_readonly_fields = ('service',)
|
change_readonly_fields = ('service',)
|
||||||
plugin = SoftwareService
|
plugin = SoftwareService
|
||||||
|
|
|
@ -17,7 +17,7 @@ class UNIXUserController(ServiceController):
|
||||||
"""
|
"""
|
||||||
verbose_name = _("UNIX user")
|
verbose_name = _("UNIX user")
|
||||||
model = 'systemusers.SystemUser'
|
model = 'systemusers.SystemUser'
|
||||||
actions = ('save', 'delete', 'set_permission', 'validate_path_exists', 'create_link')
|
actions = ('save', 'delete', 'set_permission', 'validate_paths_exist', 'create_link')
|
||||||
doc_settings = (settings, (
|
doc_settings = (settings, (
|
||||||
'SYSTEMUSERS_DEFAULT_GROUP_MEMBERS',
|
'SYSTEMUSERS_DEFAULT_GROUP_MEMBERS',
|
||||||
'SYSTEMUSERS_MOVE_ON_DELETE_PATH',
|
'SYSTEMUSERS_MOVE_ON_DELETE_PATH',
|
||||||
|
@ -215,15 +215,16 @@ class UNIXUserController(ServiceController):
|
||||||
EOF""") % context
|
EOF""") % context
|
||||||
)
|
)
|
||||||
|
|
||||||
def validate_path_exists(self, user):
|
def validate_paths_exist(self, user):
|
||||||
context = {
|
for path in user.paths_to_validate:
|
||||||
'path': user.path_to_validate,
|
context = {
|
||||||
}
|
'path': path,
|
||||||
self.append(textwrap.dedent("""
|
}
|
||||||
if [[ ! -e '%(path)s' ]]; then
|
self.append(textwrap.dedent("""
|
||||||
echo "%(path)s path does not exists." >&2
|
if [[ ! -e '%(path)s' ]]; then
|
||||||
fi""") % context
|
echo "%(path)s path does not exists." >&2
|
||||||
)
|
fi""") % context
|
||||||
|
)
|
||||||
|
|
||||||
def get_groups(self, user):
|
def get_groups(self, user):
|
||||||
if user.is_main:
|
if user.is_main:
|
||||||
|
|
|
@ -8,9 +8,8 @@ from orchestra.contrib.orchestration import Operation
|
||||||
|
|
||||||
def validate_paths_exist(user, paths):
|
def validate_paths_exist(user, paths):
|
||||||
operations = []
|
operations = []
|
||||||
for path in paths:
|
user.paths_to_validate = paths
|
||||||
user.path_to_validate = path
|
operations.extend(Operation.create_for_action(user, 'validate_paths_exist'))
|
||||||
operations.extend(Operation.create_for_action(user, 'validate_path_exists'))
|
|
||||||
logs = Operation.execute(operations)
|
logs = Operation.execute(operations)
|
||||||
stderr = '\n'.join([log.stderr for log in logs])
|
stderr = '\n'.join([log.stderr for log in logs])
|
||||||
if 'path does not exists' in stderr:
|
if 'path does not exists' in stderr:
|
||||||
|
@ -42,7 +41,7 @@ def validate_home(user, data, account):
|
||||||
if 'directory' in data and data['directory']:
|
if 'directory' in data and data['directory']:
|
||||||
path = os.path.join(data['home'], data['directory'])
|
path = os.path.join(data['home'], data['directory'])
|
||||||
try:
|
try:
|
||||||
validate_path_exists(user, path)
|
validate_paths_exist(user, (path,))
|
||||||
except ValidationError as err:
|
except ValidationError as err:
|
||||||
raise ValidationError({
|
raise ValidationError({
|
||||||
'directory': err,
|
'directory': err,
|
||||||
|
|
Loading…
Reference in New Issue