Custom mailbox filters and other random inprovements0
This commit is contained in:
parent
f38eaa6ac8
commit
7386b89be6
26
TODO.md
26
TODO.md
|
@ -60,7 +60,7 @@
|
||||||
|
|
||||||
* print open invoices as proforma?
|
* print open invoices as proforma?
|
||||||
|
|
||||||
* env ORCHESTRA_MASTER_SERVER='test1.orchestra.lan' ORCHESTRA_SECOND_SERVER='test2.orchestra.lan' ORCHESTRA_SLAVE_SERVER='test3.orchestra.lan' python3 manage.py test orchestra.contrib.domains.tests.functional_tests.tests:AdminBind9BackendDomainTest --nologcapture
|
* env ORCHESTRA_MASTER_SERVER='test1.orchestra.lan' ORCHESTRA_SECOND_SERVER='test2.orchestra.lan' ORCHESTRA_SLAVE_SERVER='test3.orchestra.lan' python3 manage.py test orchestra.contrib.domains.tests.functional_tests.tests:AdminBind9BackendDomainTest --nologcapture --keepdb
|
||||||
|
|
||||||
* ForeignKey.swappable
|
* ForeignKey.swappable
|
||||||
* Field.editable
|
* Field.editable
|
||||||
|
@ -386,4 +386,26 @@ http://wiki2.dovecot.org/Pigeonhole/Sieve/Examples
|
||||||
Bash/Python/PHPBackend
|
Bash/Python/PHPBackend
|
||||||
|
|
||||||
|
|
||||||
# Gandi sync domains cancelled
|
# bill action view on a separate process. check memory consumption without debug (236m)
|
||||||
|
|
||||||
|
# services.handler as generator in order to save memory? not swell like a balloon
|
||||||
|
# mailboxes group username instead of mainuser
|
||||||
|
|
||||||
|
import uwsgi
|
||||||
|
from uwsgidecorators import timer
|
||||||
|
from django.utils import autoreload
|
||||||
|
|
||||||
|
@timer(3)
|
||||||
|
def change_code_gracefull_reload(sig):
|
||||||
|
if autoreload.code_changed():
|
||||||
|
uwsgi.reload()
|
||||||
|
# using kill to send the signal
|
||||||
|
kill -HUP `cat /tmp/project-master.pid`
|
||||||
|
# or the convenience option --reload
|
||||||
|
uwsgi --reload /tmp/project-master.pid
|
||||||
|
# or if uwsgi was started with touch-reload=/tmp/somefile
|
||||||
|
touch /tmp/somefile
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Pending vs bill(): get_billing_point() returns the next billing point, no matter if nbp > now(). pending filter filters by billed_until < now()
|
||||||
|
|
|
@ -10,6 +10,7 @@ from .serializers import AddressSerializer, MailboxSerializer
|
||||||
class AddressViewSet(LogApiMixin, AccountApiMixin, viewsets.ModelViewSet):
|
class AddressViewSet(LogApiMixin, AccountApiMixin, viewsets.ModelViewSet):
|
||||||
queryset = Address.objects.select_related('domain').prefetch_related('mailboxes').all()
|
queryset = Address.objects.select_related('domain').prefetch_related('mailboxes').all()
|
||||||
serializer_class = AddressSerializer
|
serializer_class = AddressSerializer
|
||||||
|
filter_fields = ('domain', 'mailboxes__name')
|
||||||
|
|
||||||
|
|
||||||
class MailboxViewSet(LogApiMixin, SetPasswordApiMixin, AccountApiMixin, viewsets.ModelViewSet):
|
class MailboxViewSet(LogApiMixin, SetPasswordApiMixin, AccountApiMixin, viewsets.ModelViewSet):
|
||||||
|
|
|
@ -60,9 +60,6 @@ class UNIXUserMaildirBackend(SieveFilteringMixin, ServiceController):
|
||||||
|
|
||||||
verbose_name = _("UNIX maildir user")
|
verbose_name = _("UNIX maildir user")
|
||||||
model = 'mailboxes.Mailbox'
|
model = 'mailboxes.Mailbox'
|
||||||
doc_settings = (settings,
|
|
||||||
('MAILBOXES_USE_ACCOUNT_AS_GROUP',)
|
|
||||||
)
|
|
||||||
|
|
||||||
def save(self, mailbox):
|
def save(self, mailbox):
|
||||||
context = self.get_context(mailbox)
|
context = self.get_context(mailbox)
|
||||||
|
@ -123,10 +120,9 @@ class UNIXUserMaildirBackend(SieveFilteringMixin, ServiceController):
|
||||||
super(UNIXUserMaildirBackend, self).commit()
|
super(UNIXUserMaildirBackend, self).commit()
|
||||||
|
|
||||||
def get_context(self, mailbox):
|
def get_context(self, mailbox):
|
||||||
account_as_group = settings.MAILBOXES_USE_ACCOUNT_AS_GROUP
|
|
||||||
context = {
|
context = {
|
||||||
'user': mailbox.name,
|
'user': mailbox.name,
|
||||||
'group': mailbox.account.username if account_as_group else mailbox.name,
|
'group': mailbox.name,
|
||||||
'name': mailbox.name,
|
'name': mailbox.name,
|
||||||
'password': mailbox.password if mailbox.active else '*%s' % mailbox.password,
|
'password': mailbox.password if mailbox.active else '*%s' % mailbox.password,
|
||||||
'home': mailbox.get_home(),
|
'home': mailbox.get_home(),
|
||||||
|
|
|
@ -48,12 +48,6 @@ MAILBOXES_SIEVETEST_BIN_PATH = Setting('MAILBOXES_SIEVETEST_BIN_PATH',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
MAILBOXES_USE_ACCOUNT_AS_GROUP = Setting('MAILBOXES_USE_ACCOUNT_AS_GROUP',
|
|
||||||
False,
|
|
||||||
help_text="Group used for system user based mailboxes. If <tt>False</tt> mailbox.name will be used as group."
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
MAILBOXES_VIRTUAL_MAILBOX_MAPS_PATH = Setting('MAILBOXES_VIRTUAL_MAILBOX_MAPS_PATH',
|
MAILBOXES_VIRTUAL_MAILBOX_MAPS_PATH = Setting('MAILBOXES_VIRTUAL_MAILBOX_MAPS_PATH',
|
||||||
'/etc/postfix/virtual_mailboxes'
|
'/etc/postfix/virtual_mailboxes'
|
||||||
)
|
)
|
||||||
|
@ -81,34 +75,99 @@ MAILBOXES_PASSWD_PATH = Setting('MAILBOXES_PASSWD_PATH',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
MAILBOXES_SPAM_SCORE_HEADER = Setting('MAILBOXES_SPAM_SCORE_HEADER',
|
||||||
|
'X-Spam-Score'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
MAILBOXES_SPAM_SCORE_SYMBOL = Setting('MAILBOXES_SPAM_SCORE_SYMBOL',
|
||||||
|
'',
|
||||||
|
help_text="Blank for numeric spam score.",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
MAILBOXES_MAILBOX_FILTERINGS = Setting('MAILBOXES_MAILBOX_FILTERINGS',
|
MAILBOXES_MAILBOX_FILTERINGS = Setting('MAILBOXES_MAILBOX_FILTERINGS',
|
||||||
{
|
{
|
||||||
# value: (verbose_name, filter)
|
# value: (verbose_name, filter)
|
||||||
'DISABLE': (_("Disable"), ''),
|
'DISABLE': (_("Disable"), ''),
|
||||||
'REJECT': (mark_safe_lazy(_("Reject spam (Score≥9)")), textwrap.dedent("""\
|
'REJECT': (mark_safe_lazy(_("Reject spam (Score≥8)")), (
|
||||||
require ["fileinto","regex","envelope","vacation","reject","relational","comparator-i;ascii-numeric"];
|
textwrap.dedent("""\
|
||||||
if header :value "ge" :comparator "i;ascii-numeric" "X-Spam-Score" "9" {
|
if header :contains "%(score_header)s" "%(score_value)s" {
|
||||||
discard;
|
discard;
|
||||||
stop;
|
stop;
|
||||||
}""")),
|
}""") if MAILBOXES_SPAM_SCORE_SYMBOL else
|
||||||
'REJECT5': (mark_safe_lazy(_("Reject spam (Score≥5)")), textwrap.dedent("""\
|
textwrap.dedent("""\
|
||||||
require ["fileinto","regex","envelope","vacation","reject","relational","comparator-i;ascii-numeric"];
|
require ["relational","comparator-i;ascii-numeric"];
|
||||||
if header :value "ge" :comparator "i;ascii-numeric" "X-Spam-Score" "5" {
|
if allof (
|
||||||
discard;
|
not header :matches "%(score_header)s" "-*",
|
||||||
stop;
|
header :value "ge" :comparator "i;ascii-numeric" "%(score_header)s" "8" )
|
||||||
}""")),
|
{
|
||||||
'REDIRECT': (mark_safe_lazy(_("Archive spam (Score≥9)")), textwrap.dedent("""\
|
discard;
|
||||||
require ["fileinto","regex","envelope","vacation","reject","relational","comparator-i;ascii-numeric"];
|
stop;
|
||||||
if header :value "ge" :comparator "i;ascii-numeric" "X-Spam-Score" "9" {
|
}""")) % {
|
||||||
fileinto "Spam";
|
'score_header': MAILBOXES_SPAM_SCORE_HEADER,
|
||||||
stop;
|
'score_value': MAILBOXES_SPAM_SCORE_SYMBOL*8
|
||||||
}""")),
|
}
|
||||||
'REDIRECT5': (mark_safe_lazy(_("Archive spam (Score≥5)")), textwrap.dedent("""\
|
),
|
||||||
require ["fileinto","regex","envelope","vacation","reject","relational","comparator-i;ascii-numeric"];
|
'REJECT5': (mark_safe_lazy(_("Reject spam (Score≥5)")), (
|
||||||
if header :value "ge" :comparator "i;ascii-numeric" "X-Spam-Score" "5" {
|
textwrap.dedent("""\
|
||||||
fileinto "Spam";
|
if header :contains "%(score_header)s" "%(score_value)s" {
|
||||||
stop;
|
discard;
|
||||||
}""")),
|
stop;
|
||||||
|
}""") if MAILBOXES_SPAM_SCORE_SYMBOL else
|
||||||
|
textwrap.dedent("""\
|
||||||
|
require ["relational","comparator-i;ascii-numeric"];
|
||||||
|
if allof (
|
||||||
|
not header :matches "%(score_header)s" "-*",
|
||||||
|
header :value "ge" :comparator "i;ascii-numeric" "%(score_header)s" "5" )
|
||||||
|
{
|
||||||
|
discard;
|
||||||
|
stop;
|
||||||
|
}""")) % {
|
||||||
|
'score_header': MAILBOXES_SPAM_SCORE_HEADER,
|
||||||
|
'score_value': MAILBOXES_SPAM_SCORE_SYMBOL*5
|
||||||
|
}
|
||||||
|
),
|
||||||
|
'REDIRECT': (mark_safe_lazy(_("Archive spam (Score≥8)")), (
|
||||||
|
textwrap.dedent("""\
|
||||||
|
require "fileinto";
|
||||||
|
if header :contains "%(score_header)s" "%(score_value)s" {
|
||||||
|
fileinto "Spam";
|
||||||
|
stop;
|
||||||
|
}""") if MAILBOXES_SPAM_SCORE_SYMBOL else
|
||||||
|
textwrap.dedent("""\
|
||||||
|
require ["fileinto","relational","comparator-i;ascii-numeric"];
|
||||||
|
if allof (
|
||||||
|
not header :matches "%(score_header)s" "-*",
|
||||||
|
header :value "ge" :comparator "i;ascii-numeric" "%(score_header)s" "8" )
|
||||||
|
{
|
||||||
|
fileinto "Spam";
|
||||||
|
stop;
|
||||||
|
}""")) % {
|
||||||
|
'score_header': MAILBOXES_SPAM_SCORE_HEADER,
|
||||||
|
'score_value': MAILBOXES_SPAM_SCORE_SYMBOL*8
|
||||||
|
}
|
||||||
|
),
|
||||||
|
'REDIRECT5': (mark_safe_lazy(_("Archive spam (Score≥5)")), (
|
||||||
|
textwrap.dedent("""\
|
||||||
|
require "fileinto";
|
||||||
|
if header :contains "%(score_header)s" "%(score_value)s" {
|
||||||
|
fileinto "Spam";
|
||||||
|
stop;
|
||||||
|
}""") if MAILBOXES_SPAM_SCORE_SYMBOL else
|
||||||
|
textwrap.dedent("""\
|
||||||
|
require ["fileinto","relational","comparator-i;ascii-numeric"];
|
||||||
|
if allof (
|
||||||
|
not header :matches "%(score_header)s" "-*",
|
||||||
|
header :value "ge" :comparator "i;ascii-numeric" "%(score_header)s" "5" )
|
||||||
|
{
|
||||||
|
fileinto "Spam";
|
||||||
|
stop;
|
||||||
|
}""")) % {
|
||||||
|
'score_header': MAILBOXES_SPAM_SCORE_HEADER,
|
||||||
|
'score_value': MAILBOXES_SPAM_SCORE_SYMBOL*5
|
||||||
|
}
|
||||||
|
),
|
||||||
'CUSTOM': (_("Custom filtering"), lambda mailbox: mailbox.custom_filtering),
|
'CUSTOM': (_("Custom filtering"), lambda mailbox: mailbox.custom_filtering),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -29,7 +29,10 @@ class BillSelectedOrders(object):
|
||||||
'queryset': queryset,
|
'queryset': queryset,
|
||||||
'action_checkbox_name': admin.helpers.ACTION_CHECKBOX_NAME,
|
'action_checkbox_name': admin.helpers.ACTION_CHECKBOX_NAME,
|
||||||
}
|
}
|
||||||
return self.set_options(request)
|
ret = self.set_options(request)
|
||||||
|
del(self.queryset)
|
||||||
|
del(self.context)
|
||||||
|
return ret
|
||||||
|
|
||||||
def set_options(self, request):
|
def set_options(self, request):
|
||||||
form = BillSelectedOptionsForm()
|
form = BillSelectedOptionsForm()
|
||||||
|
@ -42,7 +45,6 @@ class BillSelectedOrders(object):
|
||||||
proforma=form.cleaned_data['proforma'],
|
proforma=form.cleaned_data['proforma'],
|
||||||
new_open=form.cleaned_data['new_open'],
|
new_open=form.cleaned_data['new_open'],
|
||||||
)
|
)
|
||||||
print(self.options)
|
|
||||||
if int(request.POST.get('step')) != 3:
|
if int(request.POST.get('step')) != 3:
|
||||||
return self.select_related(request)
|
return self.select_related(request)
|
||||||
else:
|
else:
|
||||||
|
@ -142,4 +144,3 @@ def mark_as_not_ignored(modeladmin, request, queryset):
|
||||||
_("%i selected orders have been marked as not ignored.") % num,
|
_("%i selected orders have been marked as not ignored.") % num,
|
||||||
num)
|
num)
|
||||||
modeladmin.message_user(request, msg)
|
modeladmin.message_user(request, msg)
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ class BillSelectRelatedForm(AdminFormMixin, forms.Form):
|
||||||
# initial=False, required=False, help_text=_("The price may vary "
|
# initial=False, required=False, help_text=_("The price may vary "
|
||||||
# "depending on the billed orders. This options designates whether "
|
# "depending on the billed orders. This options designates whether "
|
||||||
# "all existing orders will be used for price computation or not."))
|
# "all existing orders will be used for price computation or not."))
|
||||||
|
select_all = forms.BooleanField(label=_("Select all"), required=False)
|
||||||
selected_related = forms.ModelMultipleChoiceField(label=_("Related orders"),
|
selected_related = forms.ModelMultipleChoiceField(label=_("Related orders"),
|
||||||
queryset=Order.objects.none(), widget=forms.CheckboxSelectMultiple,
|
queryset=Order.objects.none(), widget=forms.CheckboxSelectMultiple,
|
||||||
required=False)
|
required=False)
|
||||||
|
|
|
@ -12,6 +12,20 @@
|
||||||
</style>
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block extrahead %}
|
||||||
|
{{ block.super }}
|
||||||
|
<script src="{% static "admin/js/jquery.min.js" %}" type="text/javascript"></script>
|
||||||
|
<script src="{% static "admin/js/jquery.init.js" %}" type="text/javascript"></script>
|
||||||
|
<script>
|
||||||
|
var $ = django.jQuery;
|
||||||
|
|
||||||
|
$(document).ready( function () {
|
||||||
|
$('#id_select_all').click( function() {
|
||||||
|
$(":checkbox").attr('checked', $(this).is(':checked'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block breadcrumbs %}
|
{% block breadcrumbs %}
|
||||||
<div class="breadcrumbs">
|
<div class="breadcrumbs">
|
||||||
|
|
|
@ -24,7 +24,7 @@ def _compute_steps(rates, metric):
|
||||||
quantity = metric - accumulated
|
quantity = metric - accumulated
|
||||||
next_barrier = quantity
|
next_barrier = quantity
|
||||||
else:
|
else:
|
||||||
quantity = rates[ix+1].quantity - rates[ix].quantity
|
quantity = rates[ix+1].quantity - max(rates[ix].quantity, 1)
|
||||||
next_barrier = quantity
|
next_barrier = quantity
|
||||||
if rates[ix+1].price > rates[ix].price:
|
if rates[ix+1].price > rates[ix].price:
|
||||||
quantity *= fold
|
quantity *= fold
|
||||||
|
@ -52,13 +52,13 @@ def _standardize(rates):
|
||||||
std_rates = []
|
std_rates = []
|
||||||
minimal = rates[0].quantity
|
minimal = rates[0].quantity
|
||||||
for rate in rates:
|
for rate in rates:
|
||||||
if rate.quantity == 0:
|
#if rate.quantity == 0:
|
||||||
rate.quantity = 1
|
# rate.quantity = 1
|
||||||
elif rate.quantity == minimal and rate.quantity > 1:
|
if rate.quantity == minimal and rate.quantity > 0:
|
||||||
service = rate.service
|
service = rate.service
|
||||||
rate_class = type(rate)
|
rate_class = type(rate)
|
||||||
std_rates.append(
|
std_rates.append(
|
||||||
rate_class(service=service, plan=rate.plan, quantity=1, price=service.nominal_price)
|
rate_class(service=service, plan=rate.plan, quantity=0, price=service.nominal_price)
|
||||||
)
|
)
|
||||||
std_rates.append(rate)
|
std_rates.append(rate)
|
||||||
return std_rates
|
return std_rates
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
from django.contrib import admin, messages
|
from django.contrib import admin, messages
|
||||||
|
from django.contrib.contenttypes.admin import GenericTabularInline
|
||||||
|
from django.contrib.contenttypes.forms import BaseGenericInlineFormSet
|
||||||
from django.contrib.admin.utils import unquote
|
from django.contrib.admin.utils import unquote
|
||||||
from django.contrib import contenttypes
|
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
|
@ -185,7 +186,7 @@ admin.site.register(MonitorData, MonitorDataAdmin)
|
||||||
# Mokey-patching
|
# Mokey-patching
|
||||||
|
|
||||||
def resource_inline_factory(resources):
|
def resource_inline_factory(resources):
|
||||||
class ResourceInlineFormSet(contenttypes.forms.BaseGenericInlineFormSet):
|
class ResourceInlineFormSet(BaseGenericInlineFormSet):
|
||||||
def total_form_count(self, resources=resources):
|
def total_form_count(self, resources=resources):
|
||||||
return len(resources)
|
return len(resources)
|
||||||
|
|
||||||
|
@ -225,7 +226,7 @@ def resource_inline_factory(resources):
|
||||||
forms.append(self._construct_form(i, resource=resource))
|
forms.append(self._construct_form(i, resource=resource))
|
||||||
return forms
|
return forms
|
||||||
|
|
||||||
class ResourceInline(contenttypes.admin.GenericTabularInline):
|
class ResourceInline(GenericTabularInline):
|
||||||
model = ResourceData
|
model = ResourceData
|
||||||
verbose_name_plural = _("resources")
|
verbose_name_plural = _("resources")
|
||||||
form = ResourceForm
|
form = ResourceForm
|
||||||
|
|
|
@ -136,8 +136,8 @@ class ServiceHandler(plugins.Plugin, metaclass=plugins.PluginMount):
|
||||||
return eval(self.order_description, safe_locals)
|
return eval(self.order_description, safe_locals)
|
||||||
|
|
||||||
def get_billing_point(self, order, bp=None, **options):
|
def get_billing_point(self, order, bp=None, **options):
|
||||||
not_cachable = self.billing_point == self.FIXED_DATE and options.get('fixed_point')
|
cachable = bool(self.billing_point == self.FIXED_DATE and not options.get('fixed_point'))
|
||||||
if not_cachable or bp is None:
|
if not cachable or bp is None:
|
||||||
bp = options.get('billing_point') or timezone.now().date()
|
bp = options.get('billing_point') or timezone.now().date()
|
||||||
if not options.get('fixed_point'):
|
if not options.get('fixed_point'):
|
||||||
msg = ("Support for '%s' period and '%s' point is not implemented"
|
msg = ("Support for '%s' period and '%s' point is not implemented"
|
||||||
|
|
|
@ -25,7 +25,7 @@ class DomainBillingTest(BaseTestCase):
|
||||||
nominal_price=10
|
nominal_price=10
|
||||||
)
|
)
|
||||||
plan = Plan.objects.create(is_default=True, name='Default')
|
plan = Plan.objects.create(is_default=True, name='Default')
|
||||||
service.rates.create(plan=plan, quantity=1, price=0)
|
service.rates.create(plan=plan, quantity=0, price=0)
|
||||||
service.rates.create(plan=plan, quantity=2, price=10)
|
service.rates.create(plan=plan, quantity=2, price=10)
|
||||||
service.rates.create(plan=plan, quantity=4, price=9)
|
service.rates.create(plan=plan, quantity=4, price=9)
|
||||||
service.rates.create(plan=plan, quantity=6, price=6)
|
service.rates.create(plan=plan, quantity=6, price=6)
|
||||||
|
|
|
@ -19,6 +19,7 @@ class FTPTrafficMonitor(ServiceMonitor):
|
||||||
|
|
||||||
class BaseTrafficBillingTest(BaseTestCase):
|
class BaseTrafficBillingTest(BaseTestCase):
|
||||||
TRAFFIC_METRIC = 'account.resources.traffic.used'
|
TRAFFIC_METRIC = 'account.resources.traffic.used'
|
||||||
|
DEPENDENCIES = ('orchestra.contrib.resources',)
|
||||||
|
|
||||||
def create_traffic_service(self):
|
def create_traffic_service(self):
|
||||||
service = Service.objects.create(
|
service = Service.objects.create(
|
||||||
|
|
|
@ -67,11 +67,10 @@ class SettingView(generic.edit.FormView):
|
||||||
context = self.get_context_data(form=form)
|
context = self.get_context_data(form=form)
|
||||||
context['diff'] = diff
|
context['diff'] = diff
|
||||||
return self.render_to_response(context)
|
return self.render_to_response(context)
|
||||||
|
n = len(changes)
|
||||||
# Save changes
|
# Save changes
|
||||||
parser.save(changes)
|
parser.save(changes)
|
||||||
sys.touch_wsgi()
|
sys.touch_wsgi()
|
||||||
n = len(changes)
|
|
||||||
context = {
|
context = {
|
||||||
'message': ngettext(
|
'message': ngettext(
|
||||||
_("One change successfully applied, orchestra is being restarted."),
|
_("One change successfully applied, orchestra is being restarted."),
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import ast
|
import ast
|
||||||
|
import copy
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
@ -98,6 +99,7 @@ def apply(changes, settings_file=get_settings_file()):
|
||||||
""" returns settings_file content with applied changes """
|
""" returns settings_file content with applied changes """
|
||||||
updates = _find_updates(changes, settings_file)
|
updates = _find_updates(changes, settings_file)
|
||||||
content = []
|
content = []
|
||||||
|
_changes = copy.copy(changes)
|
||||||
inside = False
|
inside = False
|
||||||
lineno = None
|
lineno = None
|
||||||
if updates:
|
if updates:
|
||||||
|
@ -107,7 +109,7 @@ def apply(changes, settings_file=get_settings_file()):
|
||||||
for num, line in enumerate(handler.readlines(), 1):
|
for num, line in enumerate(handler.readlines(), 1):
|
||||||
line = line.rstrip()
|
line = line.rstrip()
|
||||||
if num == lineno:
|
if num == lineno:
|
||||||
value = changes.pop(name)
|
value = _changes.pop(name)
|
||||||
line = _format_setting(name, value)
|
line = _format_setting(name, value)
|
||||||
if line:
|
if line:
|
||||||
content.append(line)
|
content.append(line)
|
||||||
|
@ -134,7 +136,7 @@ def apply(changes, settings_file=get_settings_file()):
|
||||||
inside = False
|
inside = False
|
||||||
|
|
||||||
# insert new variables at the end of file
|
# insert new variables at the end of file
|
||||||
for name, value in changes.items():
|
for name, value in _changes.items():
|
||||||
content.append(_format_setting(name, value))
|
content.append(_format_setting(name, value))
|
||||||
return '\n'.join(content)
|
return '\n'.join(content)
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
right: 0;
|
right: 0;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
margin-top: 100px;
|
margin-top: 100px;
|
||||||
}
|
}
|
||||||
.alert-box span {
|
.alert-box span {
|
||||||
font-weight:bold;
|
font-weight:bold;
|
||||||
text-transform:uppercase;
|
text-transform:uppercase;
|
||||||
|
@ -41,14 +41,14 @@
|
||||||
count--;
|
count--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var count = 4;
|
var count = 3;
|
||||||
var timer = setInterval(function() { handleTimer(count); }, 1000);
|
var timer = setInterval(function() { handleTimer(count); }, 1000);
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<meta http-equiv="refresh" content="6">
|
<meta http-equiv="refresh" content="3">
|
||||||
<div>
|
<div>
|
||||||
<div class="alert-box warning"><span>notice: </span>{{ message }}<br> Refreshing in <span id="count_num">5</span></span>.</div>
|
<div class="alert-box warning"><span>notice: </span>{{ message }}<br> Refreshing in <span id="count_num">2</span></span>.</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -142,7 +142,11 @@ class PHPBackend(WebAppServiceMixin, ServiceController):
|
||||||
}
|
}
|
||||||
if [[ $is_last -eq 1 ]]; then
|
if [[ $is_last -eq 1 ]]; then
|
||||||
if [[ $UPDATED_APACHE -eq 1 || "$state" =~ .*RESTART$ ]]; then
|
if [[ $UPDATED_APACHE -eq 1 || "$state" =~ .*RESTART$ ]]; then
|
||||||
service apache2 status && service apache2 reload || service apache2 start
|
if [[ $(service apache2 status) ]]; then
|
||||||
|
service apache2 reload
|
||||||
|
else
|
||||||
|
service apache2 start
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
rm /dev/shm/restart.apache2.locked
|
rm /dev/shm/restart.apache2.locked
|
||||||
else
|
else
|
||||||
|
|
|
@ -11,7 +11,7 @@ from .serializers import WebsiteSerializer
|
||||||
class WebsiteViewSet(LogApiMixin, AccountApiMixin, viewsets.ModelViewSet):
|
class WebsiteViewSet(LogApiMixin, AccountApiMixin, viewsets.ModelViewSet):
|
||||||
queryset = Website.objects.prefetch_related('domains', 'content_set__webapp', 'directives').all()
|
queryset = Website.objects.prefetch_related('domains', 'content_set__webapp', 'directives').all()
|
||||||
serializer_class = WebsiteSerializer
|
serializer_class = WebsiteSerializer
|
||||||
filter_fields = ('name',)
|
filter_fields = ('name', 'domains__name')
|
||||||
|
|
||||||
def options(self, request):
|
def options(self, request):
|
||||||
metadata = super(WebsiteViewSet, self).options(request)
|
metadata = super(WebsiteViewSet, self).options(request)
|
||||||
|
|
|
@ -67,7 +67,8 @@ class Apache2Backend(ServiceController):
|
||||||
SuexecUserGroup {{ user }} {{ group }}\
|
SuexecUserGroup {{ user }} {{ group }}\
|
||||||
{% for line in extra_conf.splitlines %}
|
{% for line in extra_conf.splitlines %}
|
||||||
{{ line | safe }}{% endfor %}
|
{{ line | safe }}{% endfor %}
|
||||||
</VirtualHost>""")
|
</VirtualHost>
|
||||||
|
""")
|
||||||
).render(Context(context))
|
).render(Context(context))
|
||||||
|
|
||||||
def render_redirect_https(self, context):
|
def render_redirect_https(self, context):
|
||||||
|
@ -84,7 +85,8 @@ class Apache2Backend(ServiceController):
|
||||||
RewriteEngine On
|
RewriteEngine On
|
||||||
RewriteCond %{HTTPS} off
|
RewriteCond %{HTTPS} off
|
||||||
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
|
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
|
||||||
</VirtualHost>""")
|
</VirtualHost>
|
||||||
|
""")
|
||||||
).render(Context(context))
|
).render(Context(context))
|
||||||
|
|
||||||
def save(self, site):
|
def save(self, site):
|
||||||
|
@ -111,7 +113,7 @@ class Apache2Backend(ServiceController):
|
||||||
}""") % context
|
}""") % context
|
||||||
)
|
)
|
||||||
if context['server_name'] and site.active:
|
if context['server_name'] and site.active:
|
||||||
self.append(textwrap.dedent("""\
|
self.append(textwrap.dedent("""
|
||||||
# Enable site %(site_name)s
|
# Enable site %(site_name)s
|
||||||
if [[ ! -f %(sites_enabled)s ]]; then
|
if [[ ! -f %(sites_enabled)s ]]; then
|
||||||
a2ensite %(site_unique_name)s.conf
|
a2ensite %(site_unique_name)s.conf
|
||||||
|
@ -119,7 +121,7 @@ class Apache2Backend(ServiceController):
|
||||||
fi""") % context
|
fi""") % context
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.append(textwrap.dedent("""\
|
self.append(textwrap.dedent("""
|
||||||
# Disable site %(site_name)s
|
# Disable site %(site_name)s
|
||||||
if [[ -f %(sites_enabled)s ]]; then
|
if [[ -f %(sites_enabled)s ]]; then
|
||||||
a2dissite %(site_unique_name)s.conf;
|
a2dissite %(site_unique_name)s.conf;
|
||||||
|
@ -160,7 +162,11 @@ class Apache2Backend(ServiceController):
|
||||||
}
|
}
|
||||||
if [[ $is_last -eq 1 ]]; then
|
if [[ $is_last -eq 1 ]]; then
|
||||||
if [[ $UPDATED_APACHE -eq 1 || "$state" =~ .*RESTART$ ]]; then
|
if [[ $UPDATED_APACHE -eq 1 || "$state" =~ .*RESTART$ ]]; then
|
||||||
service apache2 status && service apache2 reload || service apache2 start
|
if [[ $(service apache2 status) ]]; then
|
||||||
|
service apache2 reload
|
||||||
|
else
|
||||||
|
service apache2 start
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
rm /dev/shm/restart.apache2.locked
|
rm /dev/shm/restart.apache2.locked
|
||||||
else
|
else
|
||||||
|
|
|
@ -212,6 +212,6 @@ class LockFile(object):
|
||||||
self.release()
|
self.release()
|
||||||
|
|
||||||
|
|
||||||
def touch_wsgi(delay=5):
|
def touch_wsgi(delay=0):
|
||||||
from . import paths
|
from . import paths
|
||||||
run('{ sleep %i && touch %s/wsgi.py; } &' % (delay, paths.get_project_dir()), async=True)
|
run('{ sleep %i && touch %s/wsgi.py; } &' % (delay, paths.get_project_dir()), async=True)
|
||||||
|
|
Loading…
Reference in New Issue