Improved settings validation

This commit is contained in:
Marc Aymerich 2015-04-27 14:54:17 +00:00
parent 9c065d401d
commit bc51b23d97
30 changed files with 567 additions and 261 deletions

View File

@ -283,6 +283,7 @@ https://code.djangoproject.com/ticket/24576
# bill confirmation: show total
# Amend lines???
# orders currency setting
# Determine the difference between data serializer used for validation and used for the rest API!
# Make PluginApiView that fills metadata and other stuff like modeladmin plugin support

View File

@ -4,7 +4,8 @@ from django.utils.translation import ugettext_lazy as _
from orchestra.settings import ORCHESTRA_BASE_DOMAIN, Setting
ACCOUNTS_TYPES = Setting('ACCOUNTS_TYPES', (
ACCOUNTS_TYPES = Setting('ACCOUNTS_TYPES',
(
('INDIVIDUAL', _("Individual")),
('ASSOCIATION', _("Association")),
('CUSTOMER', _("Customer")),
@ -17,45 +18,55 @@ ACCOUNTS_TYPES = Setting('ACCOUNTS_TYPES', (
)
ACCOUNTS_DEFAULT_TYPE = Setting('ACCOUNTS_DEFAULT_TYPE', 'INDIVIDUAL', choices=ACCOUNTS_TYPES)
ACCOUNTS_DEFAULT_TYPE = Setting('ACCOUNTS_DEFAULT_TYPE',
'INDIVIDUAL', choices=ACCOUNTS_TYPES)
ACCOUNTS_LANGUAGES = Setting('ACCOUNTS_LANGUAGES', (
ACCOUNTS_LANGUAGES = Setting('ACCOUNTS_LANGUAGES',
(
('EN', _('English')),
),
validators=[Setting.validate_choices]
)
ACCOUNTS_DEFAULT_LANGUAGE = Setting('ACCOUNTS_DEFAULT_LANGUAGE', 'EN', choices=ACCOUNTS_LANGUAGES)
ACCOUNTS_DEFAULT_LANGUAGE = Setting('ACCOUNTS_DEFAULT_LANGUAGE',
'EN',
choices=ACCOUNTS_LANGUAGES
)
ACCOUNTS_SYSTEMUSER_MODEL = Setting('ACCOUNTS_SYSTEMUSER_MODEL', 'systemusers.SystemUser',
ACCOUNTS_SYSTEMUSER_MODEL = Setting('ACCOUNTS_SYSTEMUSER_MODEL',
'systemusers.SystemUser',
validators=[Setting.validate_model_label],
)
ACCOUNTS_MAIN_PK = Setting('ACCOUNTS_MAIN_PK', 1)
ACCOUNTS_MAIN_PK = Setting('ACCOUNTS_MAIN_PK',
1
)
ACCOUNTS_CREATE_RELATED = Setting('ACCOUNTS_CREATE_RELATED', (
# <model>, <key field>, <kwargs>, <help_text>
('mailboxes.Mailbox',
'name',
{
'name': 'account.username',
'password': 'account.password',
},
_("Designates whether to creates a related mailbox with the same name and password or not."),
ACCOUNTS_CREATE_RELATED = Setting('ACCOUNTS_CREATE_RELATED',
(
# <model>, <key field>, <kwargs>, <help_text>
('mailboxes.Mailbox',
'name',
{
'name': 'account.username',
'password': 'account.password',
},
_("Designates whether to creates a related mailbox with the same name and password or not."),
),
('domains.Domain',
'name',
{
'name': '"%s.{}" % account.username.replace("_", "-")'.format(ORCHESTRA_BASE_DOMAIN),
},
_("Designates whether to creates a related subdomain &lt;username&gt;.{} or not.".format(ORCHESTRA_BASE_DOMAIN)),
),
),
('domains.Domain',
'name',
{
'name': '"%s.{}" % account.username.replace("_", "-")'.format(ORCHESTRA_BASE_DOMAIN),
},
_("Designates whether to creates a related subdomain &lt;username&gt;.{} or not.".format(ORCHESTRA_BASE_DOMAIN)),
),
))
)
ACCOUNTS_SERVICE_REPORT_TEMPLATE = Setting('ACCOUNTS_SERVICE_REPORT_TEMPLATE',

View File

@ -4,46 +4,76 @@ from django_countries import data
from orchestra.settings import ORCHESTRA_BASE_DOMAIN, Setting
BILLS_NUMBER_LENGTH = Setting('BILLS_NUMBER_LENGTH', 4)
BILLS_NUMBER_LENGTH = Setting('BILLS_NUMBER_LENGTH',
4
)
BILLS_INVOICE_NUMBER_PREFIX = Setting('BILLS_INVOICE_NUMBER_PREFIX', 'I')
BILLS_INVOICE_NUMBER_PREFIX = Setting('BILLS_INVOICE_NUMBER_PREFIX',
'I'
)
BILLS_AMENDMENT_INVOICE_NUMBER_PREFIX = Setting('BILLS_AMENDMENT_INVOICE_NUMBER_PREFIX', 'A')
BILLS_AMENDMENT_INVOICE_NUMBER_PREFIX = Setting('BILLS_AMENDMENT_INVOICE_NUMBER_PREFIX',
'A'
)
BILLS_FEE_NUMBER_PREFIX = Setting('BILLS_FEE_NUMBER_PREFIX', 'F')
BILLS_FEE_NUMBER_PREFIX = Setting('BILLS_FEE_NUMBER_PREFIX',
'F'
)
BILLS_AMENDMENT_FEE_NUMBER_PREFIX = Setting('BILLS_AMENDMENT_FEE_NUMBER_PREFIX', 'B')
BILLS_AMENDMENT_FEE_NUMBER_PREFIX = Setting('BILLS_AMENDMENT_FEE_NUMBER_PREFIX',
'B'
)
BILLS_PROFORMA_NUMBER_PREFIX = Setting('BILLS_PROFORMA_NUMBER_PREFIX', 'P')
BILLS_PROFORMA_NUMBER_PREFIX = Setting('BILLS_PROFORMA_NUMBER_PREFIX',
'P'
)
BILLS_DEFAULT_TEMPLATE = Setting('BILLS_DEFAULT_TEMPLATE', 'bills/microspective.html')
BILLS_DEFAULT_TEMPLATE = Setting('BILLS_DEFAULT_TEMPLATE',
'bills/microspective.html'
)
BILLS_FEE_TEMPLATE = Setting('BILLS_FEE_TEMPLATE', 'bills/microspective-fee.html')
BILLS_FEE_TEMPLATE = Setting('BILLS_FEE_TEMPLATE',
'bills/microspective-fee.html'
)
BILLS_PROFORMA_TEMPLATE = Setting('BILLS_PROFORMA_TEMPLATE', 'bills/microspective-proforma.html')
BILLS_PROFORMA_TEMPLATE = Setting('BILLS_PROFORMA_TEMPLATE',
'bills/microspective-proforma.html'
)
BILLS_CURRENCY = Setting('BILLS_CURRENCY', 'euro')
BILLS_CURRENCY = Setting('BILLS_CURRENCY',
'euro'
)
BILLS_SELLER_PHONE = Setting('BILLS_SELLER_PHONE', '111-112-11-222')
BILLS_SELLER_PHONE = Setting('BILLS_SELLER_PHONE',
'111-112-11-222'
)
BILLS_SELLER_EMAIL = Setting('BILLS_SELLER_EMAIL', 'sales@{}'.format(ORCHESTRA_BASE_DOMAIN))
BILLS_SELLER_EMAIL = Setting('BILLS_SELLER_EMAIL',
'sales@{}'.format(ORCHESTRA_BASE_DOMAIN),
help_text="Uses ORCHESTRA_BASE_DOMAIN by default.",
)
BILLS_SELLER_WEBSITE = Setting('BILLS_SELLER_WEBSITE', 'www.{}'.format(ORCHESTRA_BASE_DOMAIN))
BILLS_SELLER_WEBSITE = Setting('BILLS_SELLER_WEBSITE',
'www.{}'.format(ORCHESTRA_BASE_DOMAIN),
help_text="Uses ORCHESTRA_BASE_DOMAIN by default.",
)
BILLS_SELLER_BANK_ACCOUNT = Setting('BILLS_SELLER_BANK_ACCOUNT', '0000 0000 00 00000000 (Orchestra Bank)')
BILLS_SELLER_BANK_ACCOUNT = Setting('BILLS_SELLER_BANK_ACCOUNT',
'0000 0000 00 00000000 (Orchestra Bank)'
)
BILLS_EMAIL_NOTIFICATION_TEMPLATE = Setting('BILLS_EMAIL_NOTIFICATION_TEMPLATE',
@ -51,19 +81,24 @@ BILLS_EMAIL_NOTIFICATION_TEMPLATE = Setting('BILLS_EMAIL_NOTIFICATION_TEMPLATE',
)
BILLS_ORDER_MODEL = Setting('BILLS_ORDER_MODEL', 'orders.Order',
BILLS_ORDER_MODEL = Setting('BILLS_ORDER_MODEL',
'orders.Order',
validators=[Setting.validate_model_label]
)
BILLS_CONTACT_DEFAULT_CITY = Setting('BILLS_CONTACT_DEFAULT_CITY', 'Barcelona')
BILLS_CONTACT_DEFAULT_CITY = Setting('BILLS_CONTACT_DEFAULT_CITY',
'Barcelona'
)
BILLS_CONTACT_COUNTRIES = Setting('BILLS_CONTACT_COUNTRIES', tuple((k,v) for k,v in data.COUNTRIES.items()),
BILLS_CONTACT_COUNTRIES = Setting('BILLS_CONTACT_COUNTRIES',
tuple((k,v) for k,v in data.COUNTRIES.items()),
serializable=False
)
BILLS_CONTACT_DEFAULT_COUNTRY = Setting('BILLS_CONTACT_DEFAULT_COUNTRY', 'ES',
BILLS_CONTACT_DEFAULT_COUNTRY = Setting('BILLS_CONTACT_DEFAULT_COUNTRY',
'ES',
choices=BILLS_CONTACT_COUNTRIES
)

View File

@ -1,7 +1,10 @@
from orchestra.core.validators import validate_hostname
from orchestra.settings import Setting
DATABASES_TYPE_CHOICES = Setting('DATABASES_TYPE_CHOICES', (
DATABASES_TYPE_CHOICES = Setting('DATABASES_TYPE_CHOICES',
(
('mysql', 'MySQL'),
('postgres', 'PostgreSQL'),
),
@ -9,7 +12,13 @@ DATABASES_TYPE_CHOICES = Setting('DATABASES_TYPE_CHOICES', (
)
DATABASES_DEFAULT_TYPE = Setting('DATABASES_DEFAULT_TYPE', 'mysql', choices=DATABASES_TYPE_CHOICES)
DATABASES_DEFAULT_TYPE = Setting('DATABASES_DEFAULT_TYPE',
'mysql',
choices=DATABASES_TYPE_CHOICES,
)
DATABASES_DEFAULT_HOST = Setting('DATABASES_DEFAULT_HOST', 'localhost')
DATABASES_DEFAULT_HOST = Setting('DATABASES_DEFAULT_HOST',
'localhost',
validators=[validate_hostname],
)

View File

@ -1,39 +1,49 @@
from orchestra.core.validators import validate_ipv4_address, validate_ipv6_address
from orchestra.core.validators import validate_ipv4_address, validate_ipv6_address, validate_ip_address
from orchestra.settings import ORCHESTRA_BASE_DOMAIN, Setting
from .validators import validate_zone_interval, validate_mx_record, validate_domain_name
DOMAINS_DEFAULT_NAME_SERVER = Setting('DOMAINS_DEFAULT_NAME_SERVER',
'ns.{}'.format(ORCHESTRA_BASE_DOMAIN)
'ns.{}'.format(ORCHESTRA_BASE_DOMAIN),
validators=[validate_domain_name],
help_text="Uses <tt>ORCHESTRA_BASE_DOMAIN</tt> by default."
)
DOMAINS_DEFAULT_HOSTMASTER = Setting('DOMAINS_DEFAULT_HOSTMASTER',
'hostmaster@{}'.format(ORCHESTRA_BASE_DOMAIN)
'hostmaster@{}'.format(ORCHESTRA_BASE_DOMAIN),
help_text="Uses <tt>ORCHESTRA_BASE_DOMAIN</tt> by default."
)
DOMAINS_DEFAULT_TTL = Setting('DOMAINS_DEFAULT_TTL',
'1h'
'1h',
validators=[validate_zone_interval],
)
DOMAINS_DEFAULT_REFRESH = Setting('DOMAINS_DEFAULT_REFRESH',
'1d'
'1d',
validators=[validate_zone_interval],
)
DOMAINS_DEFAULT_RETRY = Setting('DOMAINS_DEFAULT_RETRY',
'2h'
'2h',
validators=[validate_zone_interval],
)
DOMAINS_DEFAULT_EXPIRATION = Setting('DOMAINS_DEFAULT_EXPIRATION',
'4w'
'4w',
validators=[validate_zone_interval],
)
DOMAINS_DEFAULT_MIN_CACHING_TIME = Setting('DOMAINS_DEFAULT_MIN_CACHING_TIME',
'1h'
'1h',
validators=[validate_zone_interval],
)
@ -43,17 +53,17 @@ DOMAINS_ZONE_PATH = Setting('DOMAINS_ZONE_PATH',
DOMAINS_MASTERS_PATH = Setting('DOMAINS_MASTERS_PATH',
'/etc/bind/named.conf.local'
'/etc/bind/named.conf.local',
)
DOMAINS_SLAVES_PATH = Setting('DOMAINS_SLAVES_PATH',
'/etc/bind/named.conf.local'
'/etc/bind/named.conf.local',
)
DOMAINS_CHECKZONE_BIN_PATH = Setting('DOMAINS_CHECKZONE_BIN_PATH',
'/usr/sbin/named-checkzone -i local -k fail -n fail'
'/usr/sbin/named-checkzone -i local -k fail -n fail',
)
@ -63,7 +73,8 @@ DOMAINS_ZONE_VALIDATION_TMP_DIR = Setting('DOMAINS_ZONE_VALIDATION_TMP_DIR',
)
DOMAINS_DEFAULT_A = Setting('DOMAINS_DEFAULT_A', '10.0.3.13',
DOMAINS_DEFAULT_A = Setting('DOMAINS_DEFAULT_A',
'10.0.3.13',
validators=[validate_ipv4_address]
)
@ -73,19 +84,28 @@ DOMAINS_DEFAULT_AAAA = Setting('DOMAINS_DEFAULT_AAAA', '',
)
DOMAINS_DEFAULT_MX = Setting('DOMAINS_DEFAULT_MX', (
'10 mail.{}.'.format(ORCHESTRA_BASE_DOMAIN),
'10 mail2.{}.'.format(ORCHESTRA_BASE_DOMAIN),
))
DOMAINS_DEFAULT_MX = Setting('DOMAINS_DEFAULT_MX',
default=(
'10 mail.{}.'.format(ORCHESTRA_BASE_DOMAIN),
'10 mail2.{}.'.format(ORCHESTRA_BASE_DOMAIN),
),
validators=[lambda mxs: map(validate_mx_record, mxs)],
help_text="Uses <tt>ORCHESTRA_BASE_DOMAIN</tt> by default."
)
DOMAINS_DEFAULT_NS = Setting('DOMAINS_DEFAULT_NS', (
'ns1.{}.'.format(ORCHESTRA_BASE_DOMAIN),
'ns2.{}.'.format(ORCHESTRA_BASE_DOMAIN),
))
DOMAINS_DEFAULT_NS = Setting('DOMAINS_DEFAULT_NS',
default=(
'ns1.{}.'.format(ORCHESTRA_BASE_DOMAIN),
'ns2.{}.'.format(ORCHESTRA_BASE_DOMAIN),
),
validators=[lambda nss: map(validate_domain_name, nss)],
help_text="Uses <tt>ORCHESTRA_BASE_DOMAIN</tt> by default."
)
DOMAINS_FORBIDDEN = Setting('DOMAINS_FORBIDDEN', '',
DOMAINS_FORBIDDEN = Setting('DOMAINS_FORBIDDEN',
'',
help_text=(
"This setting prevents users from providing random domain names, i.e. google.com<br>"
"You can generate a 5K forbidden domains list from Alexa's top 1M:<br>"
@ -98,11 +118,13 @@ DOMAINS_FORBIDDEN = Setting('DOMAINS_FORBIDDEN', '',
DOMAINS_MASTERS = Setting('DOMAINS_MASTERS',
(),
validators=[lambda masters: map(validate_ip_address, masters)],
help_text="Additional master server ip addresses other than autodiscovered by router.get_servers()."
)
DOMAINS_SLAVES = Setting('DOMAINS_SLAVES',
(),
validators=[lambda slaves: map(validate_ip_address, slaves)],
help_text="Additional slave server ip addresses other than autodiscovered by router.get_servers()."
)

View File

@ -8,14 +8,14 @@ from orchestra.core.validators import validate_hostname
from orchestra.utils import paths
from orchestra.utils.sys import run
from . import settings
from .. import domains
def validate_allowed_domain(value):
context = {
'site_dir': paths.get_site_dir()
}
fname = settings.DOMAINS_FORBIDDEN
fname = domains.settings.DOMAINS_FORBIDDEN
if fname:
fname = fname % context
with open(fname, 'r') as forbidden:
@ -108,8 +108,8 @@ def validate_soa_record(value):
def validate_zone(zone):
""" Ultimate zone file validation using named-checkzone """
zone_name = zone.split()[0][:-1]
zone_path = os.path.join(settings.DOMAINS_ZONE_VALIDATION_TMP_DIR, zone_name)
checkzone = settings.DOMAINS_CHECKZONE_BIN_PATH
zone_path = os.path.join(domains.settings.DOMAINS_ZONE_VALIDATION_TMP_DIR, zone_name)
checkzone = domains.settings.DOMAINS_CHECKZONE_BIN_PATH
try:
with open(zone_path, 'wb') as f:
f.write(zone.encode('ascii'))

View File

@ -1,7 +1,11 @@
from orchestra.settings import Setting
ISSUES_SUPPORT_EMAILS = Setting('ISSUES_SUPPORT_EMAILS', ())
ISSUES_SUPPORT_EMAILS = Setting('ISSUES_SUPPORT_EMAILS',
()
)
ISSUES_NOTIFY_SUPERUSERS = Setting('ISSUES_NOTIFY_SUPERUSERS', True)
ISSUES_NOTIFY_SUPERUSERS = Setting('ISSUES_NOTIFY_SUPERUSERS',
True
)

View File

@ -1,26 +1,39 @@
from orchestra.settings import ORCHESTRA_BASE_DOMAIN, Setting
LISTS_DOMAIN_MODEL = Setting('LISTS_DOMAIN_MODEL', 'domains.Domain',
LISTS_DOMAIN_MODEL = Setting('LISTS_DOMAIN_MODEL',
'domains.Domain',
validators=[Setting.validate_model_label]
)
LISTS_DEFAULT_DOMAIN = Setting('LISTS_DEFAULT_DOMAIN', 'lists.{}'.format(ORCHESTRA_BASE_DOMAIN))
LISTS_LIST_URL = Setting('LISTS_LIST_URL',
'https://lists.{}/mailman/listinfo/%(name)s'.format(ORCHESTRA_BASE_DOMAIN)
LISTS_DEFAULT_DOMAIN = Setting('LISTS_DEFAULT_DOMAIN',
'lists.{}'.format(ORCHESTRA_BASE_DOMAIN),
help_text="Uses <tt>ORCHESTRA_BASE_DOMAIN</tt> by default."
)
LISTS_MAILMAN_POST_LOG_PATH = Setting('LISTS_MAILMAN_POST_LOG_PATH', '/var/log/mailman/post')
LISTS_LIST_URL = Setting('LISTS_LIST_URL',
'https://lists.{}/mailman/listinfo/%(name)s'.format(ORCHESTRA_BASE_DOMAIN),
help_text="Uses <tt>ORCHESTRA_BASE_DOMAIN</tt> by default."
)
LISTS_MAILMAN_ROOT_DIR = Setting('LISTS_MAILMAN_ROOT_DIR', '/var/lib/mailman')
LISTS_MAILMAN_POST_LOG_PATH = Setting('LISTS_MAILMAN_POST_LOG_PATH',
'/var/log/mailman/post'
)
LISTS_VIRTUAL_ALIAS_PATH = Setting('LISTS_VIRTUAL_ALIAS_PATH', '/etc/postfix/mailman_virtual_aliases')
LISTS_MAILMAN_ROOT_DIR = Setting('LISTS_MAILMAN_ROOT_DIR',
'/var/lib/mailman'
)
LISTS_VIRTUAL_ALIAS_DOMAINS_PATH = Setting('LISTS_VIRTUAL_ALIAS_DOMAINS_PATH', '/etc/postfix/mailman_virtual_domains')
LISTS_VIRTUAL_ALIAS_PATH = Setting('LISTS_VIRTUAL_ALIAS_PATH',
'/etc/postfix/mailman_virtual_aliases'
)
LISTS_VIRTUAL_ALIAS_DOMAINS_PATH = Setting('LISTS_VIRTUAL_ALIAS_DOMAINS_PATH',
'/etc/postfix/mailman_virtual_domains'
)

View File

@ -7,12 +7,20 @@ from orchestra.core.validators import validate_name
from orchestra.settings import ORCHESTRA_BASE_DOMAIN, Setting
_names = ('name', 'username')
_backend_names = _names + ('group', 'home')
MAILBOXES_DOMAIN_MODEL = Setting('MAILBOXES_DOMAIN_MODEL', 'domains.Domain',
validators=[Setting.validate_model_label]
)
MAILBOXES_HOME = Setting('MAILBOXES_HOME', '/home/%(name)s/')
MAILBOXES_HOME = Setting('MAILBOXES_HOME',
'/home/%(name)s/',
help_text="Available fromat names: <tt>%s</tt>" % ', '.join(_names),
validators=[Setting.string_format_validator(_names)],
)
MAILBOXES_SIEVE_PATH = Setting('MAILBOXES_SIEVE_PATH',
@ -20,10 +28,13 @@ MAILBOXES_SIEVE_PATH = Setting('MAILBOXES_SIEVE_PATH',
)
MAILBOXES_SIEVETEST_PATH = Setting('MAILBOXES_SIEVETEST_PATH', '/dev/shm')
MAILBOXES_SIEVETEST_PATH = Setting('MAILBOXES_SIEVETEST_PATH',
'/dev/shm'
)
MAILBOXES_SIEVETEST_BIN_PATH = Setting('MAILBOXES_SIEVETEST_BIN_PATH', '%(orchestra_root)s/bin/sieve-test',
MAILBOXES_SIEVETEST_BIN_PATH = Setting('MAILBOXES_SIEVETEST_BIN_PATH',
'%(orchestra_root)s/bin/sieve-test',
validators=[Setting.string_format_validator(('orchestra_root',))]
)
@ -43,47 +54,66 @@ MAILBOXES_VIRTUAL_ALIAS_DOMAINS_PATH = Setting('MAILBOXES_VIRTUAL_ALIAS_DOMAINS_
)
MAILBOXES_LOCAL_DOMAIN = Setting('MAILBOXES_LOCAL_DOMAIN', ORCHESTRA_BASE_DOMAIN,
validators=[validate_name]
MAILBOXES_LOCAL_DOMAIN = Setting('MAILBOXES_LOCAL_DOMAIN',
ORCHESTRA_BASE_DOMAIN,
validators=[validate_name],
help_text="Defaults to <tt>ORCHESTRA_BASE_DOMAIN</tt>."
)
MAILBOXES_PASSWD_PATH = Setting('MAILBOXES_PASSWD_PATH', '/etc/dovecot/passwd')
MAILBOXES_PASSWD_PATH = Setting('MAILBOXES_PASSWD_PATH',
'/etc/dovecot/passwd'
)
MAILBOXES_MAILBOX_FILTERINGS = Setting('MAILBOXES_MAILBOX_FILTERINGS', {
# value: (verbose_name, filter)
'DISABLE': (_("Disable"), ''),
'REJECT': (_("Reject spam"), textwrap.dedent("""
require ["fileinto","regex","envelope","vacation","reject","relational","comparator-i;ascii-numeric"];
if header :value "ge" :comparator "i;ascii-numeric" "X-Spam-Score" "5" {
discard;
stop;
}""")),
'REDIRECT': (_("Archive spam"), textwrap.dedent("""
require ["fileinto","regex","envelope","vacation","reject","relational","comparator-i;ascii-numeric"];
if header :value "ge" :comparator "i;ascii-numeric" "X-Spam-Score" "5" {
fileinto "Spam";
stop;
}""")),
'CUSTOM': (_("Custom filtering"), lambda mailbox: mailbox.custom_filtering),
})
MAILBOXES_MAILBOX_FILTERINGS = Setting('MAILBOXES_MAILBOX_FILTERINGS',
{
# value: (verbose_name, filter)
'DISABLE': (_("Disable"), ''),
'REJECT': (_("Reject spam"), textwrap.dedent("""
require ["fileinto","regex","envelope","vacation","reject","relational","comparator-i;ascii-numeric"];
if header :value "ge" :comparator "i;ascii-numeric" "X-Spam-Score" "5" {
discard;
stop;
}""")),
'REDIRECT': (_("Archive spam"), textwrap.dedent("""
require ["fileinto","regex","envelope","vacation","reject","relational","comparator-i;ascii-numeric"];
if header :value "ge" :comparator "i;ascii-numeric" "X-Spam-Score" "5" {
fileinto "Spam";
stop;
}""")),
'CUSTOM': (_("Custom filtering"), lambda mailbox: mailbox.custom_filtering),
}
)
MAILBOXES_MAILBOX_DEFAULT_FILTERING = Setting('MAILBOXES_MAILBOX_DEFAULT_FILTERING', 'REDIRECT',
MAILBOXES_MAILBOX_DEFAULT_FILTERING = Setting('MAILBOXES_MAILBOX_DEFAULT_FILTERING',
'REDIRECT',
choices=tuple((k, v[0]) for k,v in MAILBOXES_MAILBOX_FILTERINGS.items())
)
MAILBOXES_MAILDIRSIZE_PATH = Setting('MAILBOXES_MAILDIRSIZE_PATH', '%(home)s/Maildir/maildirsize')
MAILBOXES_LOCAL_ADDRESS_DOMAIN = Setting('MAILBOXES_LOCAL_ADDRESS_DOMAIN', ORCHESTRA_BASE_DOMAIN,
validators=[validate_name]
MAILBOXES_MAILDIRSIZE_PATH = Setting('MAILBOXES_MAILDIRSIZE_PATH',
'%(home)s/Maildir/maildirsize',
help_text="Available fromat names: <tt>%s</tt>" % ', '.join(_backend_names),
validators=[Setting.string_format_validator(_backend_names)],
)
MAILBOXES_MAIL_LOG_PATH = Setting('MAILBOXES_MAIL_LOG_PATH', '/var/log/mail.log')
MAILBOXES_LOCAL_ADDRESS_DOMAIN = Setting('MAILBOXES_LOCAL_ADDRESS_DOMAIN',
ORCHESTRA_BASE_DOMAIN,
validators=[validate_name],
help_text="Defaults to <tt>ORCHESTRA_BASE_DOMAIN</tt>."
)
MAILBOXES_MOVE_ON_DELETE_PATH = Setting('MAILBOXES_MOVE_ON_DELETE_PATH', '')
MAILBOXES_MAIL_LOG_PATH = Setting('MAILBOXES_MAIL_LOG_PATH',
'/var/log/mail.log'
)
MAILBOXES_MOVE_ON_DELETE_PATH = Setting('MAILBOXES_MOVE_ON_DELETE_PATH',
'',
help_text="Available fromat names: <tt>%s</tt>" % ', '.join(_backend_names),
validators=[Setting.string_format_validator(_backend_names)],
)

View File

@ -10,6 +10,7 @@ from orchestra.admin.utils import admin_link
from orchestra.contrib.accounts.admin import AccountAdminMixin
from orchestra.plugins import PluginModelAdapter
from orchestra.plugins.admin import SelectPluginAdminMixin
from orchestra.utils.python import import_class
from . import settings
from .models import MiscService, Miscellaneous
@ -92,7 +93,8 @@ class MiscellaneousAdmin(AccountAdminMixin, SelectPluginAdminMixin, admin.ModelA
service = self.get_service(obj)
def clean_identifier(self, service=service):
identifier = self.cleaned_data['identifier']
validator = settings.MISCELLANEOUS_IDENTIFIER_VALIDATORS.get(service.name, None)
validator_path = settings.MISCELLANEOUS_IDENTIFIER_VALIDATORS.get(service.name, None)
validator = import_class(validator_path)
if validator:
validator(identifier)
return identifier

View File

@ -1,6 +1,8 @@
from orchestra.settings import Setting
MISCELLANEOUS_IDENTIFIER_VALIDATORS = Setting('MISCELLANEOUS_IDENTIFIER_VALIDATORS', {
# <miscservice__name>: <validator_function>
})
MISCELLANEOUS_IDENTIFIER_VALIDATORS = Setting('MISCELLANEOUS_IDENTIFIER_VALIDATORS',
{
# <miscservice__name>: <validator_function>
}
)

View File

@ -1,35 +1,43 @@
from datetime import timedelta
from os import path
from orchestra.settings import Setting
ORCHESTRATION_OS_CHOICES = Setting('ORCHESTRATION_OS_CHOICES', (
ORCHESTRATION_OS_CHOICES = Setting('ORCHESTRATION_OS_CHOICES',
(
('LINUX', "Linux"),
),
validators=[Setting.validate_choices]
)
ORCHESTRATION_DEFAULT_OS = Setting('ORCHESTRATION_DEFAULT_OS', 'LINUX',
choices=ORCHESTRATION_OS_CHOICES)
ORCHESTRATION_DEFAULT_OS = Setting('ORCHESTRATION_DEFAULT_OS',
'LINUX',
choices=ORCHESTRATION_OS_CHOICES
)
ORCHESTRATION_SSH_KEY_PATH = Setting('ORCHESTRATION_SSH_KEY_PATH',
path.join(path.expanduser('~'), '.ssh/id_rsa'))
path.join(path.expanduser('~'), '.ssh/id_rsa')
)
ORCHESTRATION_ROUTER = Setting('ORCHESTRATION_ROUTER', 'orchestra.contrib.orchestration.models.Route',
ORCHESTRATION_ROUTER = Setting('ORCHESTRATION_ROUTER',
'orchestra.contrib.orchestration.models.Route',
validators=[Setting.validate_import_class]
)
ORCHESTRATION_TEMP_SCRIPT_DIR = Setting('ORCHESTRATION_TEMP_SCRIPT_DIR', '/dev/shm')
ORCHESTRATION_DISABLE_EXECUTION = Setting('ORCHESTRATION_DISABLE_EXECUTION', False)
ORCHESTRATION_BACKEND_CLEANUP_DELTA = Setting('ORCHESTRATION_BACKEND_CLEANUP_DELTA',
timedelta(days=15)
ORCHESTRATION_TEMP_SCRIPT_DIR = Setting('ORCHESTRATION_TEMP_SCRIPT_DIR',
'/dev/shm'
)
ORCHESTRATION_DISABLE_EXECUTION = Setting('ORCHESTRATION_DISABLE_EXECUTION',
False
)
ORCHESTRATION_BACKEND_CLEANUP_DAYS = Setting('ORCHESTRATION_BACKEND_CLEANUP_DAYS',
15
)

View File

@ -1,3 +1,5 @@
from datetime import timedelta
from celery.task.schedules import crontab
from celery.decorators import periodic_task
from django.utils import timezone
@ -7,5 +9,6 @@ from .models import BackendLog
@periodic_task(run_every=crontab(hour=7, minute=30, day_of_week=1))
def backend_logs_cleanup(run_every=run_every):
epoch = timezone.now()-settings.ORCHESTRATION_BACKEND_CLEANUP_DELTA
days = settings.ORCHESTRATION_BACKEND_CLEANUP_DAYS
epoch = timezone.now()-timedelta(days=days)
BackendLog.objects.filter(created_at__lt=epoch).delete()

View File

@ -1,19 +1,22 @@
from orchestra.settings import Setting
ORDERS_BILLING_BACKEND = Setting('ORDERS_BILLING_BACKEND', 'orchestra.contrib.orders.billing.BillsBackend',
ORDERS_BILLING_BACKEND = Setting('ORDERS_BILLING_BACKEND',
'orchestra.contrib.orders.billing.BillsBackend',
validators=[Setting.validate_import_class],
help_text="Pluggable backend for bill generation.",
)
ORDERS_SERVICE_MODEL = Setting('ORDERS_SERVICE_MODEL', 'services.Service',
ORDERS_SERVICE_MODEL = Setting('ORDERS_SERVICE_MODEL',
'services.Service',
validators=[Setting.validate_model_label],
help_text="Pluggable service class."
help_text="Pluggable service class.",
)
ORDERS_EXCLUDED_APPS = Setting('ORDERS_EXCLUDED_APPS', (
ORDERS_EXCLUDED_APPS = Setting('ORDERS_EXCLUDED_APPS',
(
'orders',
'admin',
'contenttypes',
@ -28,7 +31,8 @@ ORDERS_EXCLUDED_APPS = Setting('ORDERS_EXCLUDED_APPS', (
)
ORDERS_METRIC_ERROR = Setting('ORDERS_METRIC_ERROR', 0.01,
ORDERS_METRIC_ERROR = Setting('ORDERS_METRIC_ERROR',
0.01,
help_text=("Only account for significative changes.<br>"
"metric_storage new value: <tt>lastvalue*(1+threshold) > currentvalue or lastvalue*threshold < currentvalue</tt>.")
"metric_storage new value: <tt>lastvalue*(1+threshold) > currentvalue or lastvalue*threshold < currentvalue</tt>."),
)

View File

@ -3,22 +3,33 @@ from orchestra.settings import Setting
from .. import payments
PAYMENT_CURRENCY = Setting('PAYMENT_CURRENCY', 'Eur')
PAYMENT_CURRENCY = Setting('PAYMENT_CURRENCY',
'Eur'
)
PAYMENTS_DD_CREDITOR_NAME = Setting('PAYMENTS_DD_CREDITOR_NAME', 'Orchestra')
PAYMENTS_DD_CREDITOR_NAME = Setting('PAYMENTS_DD_CREDITOR_NAME',
'Orchestra'
)
PAYMENTS_DD_CREDITOR_IBAN = Setting('PAYMENTS_DD_CREDITOR_IBAN', 'IE98BOFI90393912121212')
PAYMENTS_DD_CREDITOR_IBAN = Setting('PAYMENTS_DD_CREDITOR_IBAN',
'IE98BOFI90393912121212'
)
PAYMENTS_DD_CREDITOR_BIC = Setting('PAYMENTS_DD_CREDITOR_BIC', 'BOFIIE2D')
PAYMENTS_DD_CREDITOR_BIC = Setting('PAYMENTS_DD_CREDITOR_BIC',
'BOFIIE2D'
)
PAYMENTS_DD_CREDITOR_AT02_ID = Setting('PAYMENTS_DD_CREDITOR_AT02_ID', 'InvalidAT02ID')
PAYMENTS_DD_CREDITOR_AT02_ID = Setting('PAYMENTS_DD_CREDITOR_AT02_ID',
'InvalidAT02ID'
)
PAYMENTS_ENABLED_METHODS = Setting('PAYMENTS_ENABLED_METHODS', (
PAYMENTS_ENABLED_METHODS = Setting('PAYMENTS_ENABLED_METHODS',
(
'orchestra.contrib.payments.methods.sepadirectdebit.SEPADirectDebit',
'orchestra.contrib.payments.methods.creditcard.CreditCard',
),

View File

@ -3,7 +3,8 @@ from orchestra.settings import ORCHESTRA_BASE_DOMAIN, Setting
from .. import saas
SAAS_ENABLED_SERVICES = Setting('SAAS_ENABLED_SERVICES', (
SAAS_ENABLED_SERVICES = Setting('SAAS_ENABLED_SERVICES',
(
'orchestra.contrib.saas.services.moodle.MoodleService',
'orchestra.contrib.saas.services.bscw.BSCWService',
'orchestra.contrib.saas.services.gitlab.GitLabService',
@ -19,11 +20,14 @@ SAAS_ENABLED_SERVICES = Setting('SAAS_ENABLED_SERVICES', (
)
SAAS_WORDPRESS_ADMIN_PASSWORD = Setting('SAAS_WORDPRESSMU_ADMIN_PASSWORD', 'secret')
SAAS_WORDPRESS_ADMIN_PASSWORD = Setting('SAAS_WORDPRESSMU_ADMIN_PASSWORD',
'secret'
)
SAAS_WORDPRESS_BASE_URL = Setting('SAAS_WORDPRESS_BASE_URL',
'https://blogs.{}/'.format(ORCHESTRA_BASE_DOMAIN)
'https://blogs.{}/'.format(ORCHESTRA_BASE_DOMAIN),
help_text="Uses <tt>ORCHESTRA_BASE_DOMAIN</tt> by default.",
)
@ -38,22 +42,25 @@ SAAS_DOKUWIKI_FARM_PATH = Setting('WEBSITES_DOKUWIKI_FARM_PATH',
SAAS_DRUPAL_SITES_PATH = Setting('WEBSITES_DRUPAL_SITES_PATH',
'/home/httpd/htdocs/drupal-mu/sites/%(site_name)s'
'/home/httpd/htdocs/drupal-mu/sites/%(site_name)s',
)
SAAS_PHPLIST_DB_NAME = Setting('SAAS_PHPLIST_DB_NAME',
'phplist_mu'
'phplist_mu',
)
SAAS_PHPLIST_BASE_DOMAIN = Setting('SAAS_PHPLIST_BASE_DOMAIN',
'lists.{}'.format(ORCHESTRA_BASE_DOMAIN)
'lists.{}'.format(ORCHESTRA_BASE_DOMAIN),
help_text="Uses <tt>ORCHESTRA_BASE_DOMAIN</tt> by default.",
)
SAAS_SEAFILE_DOMAIN = Setting('SAAS_SEAFILE_DOMAIN',
'seafile.{}'.format(ORCHESTRA_BASE_DOMAIN)
'seafile.{}'.format(ORCHESTRA_BASE_DOMAIN),
help_text="Uses <tt>ORCHESTRA_BASE_DOMAIN</tt> by default.",
)
@ -63,24 +70,27 @@ SAAS_SEAFILE_DEFAULT_QUOTA = Setting('SAAS_SEAFILE_DEFAULT_QUOTA',
SAAS_BSCW_DOMAIN = Setting('SAAS_BSCW_DOMAIN',
'bscw.{}'.format(ORCHESTRA_BASE_DOMAIN)
'bscw.{}'.format(ORCHESTRA_BASE_DOMAIN),
help_text="Uses <tt>ORCHESTRA_BASE_DOMAIN</tt> by default.",
)
SAAS_BSCW_DEFAULT_QUOTA = Setting('SAAS_BSCW_DEFAULT_QUOTA',
50
50,
)
SAAS_BSCW_BSADMIN_PATH = Setting('SAAS_BSCW_BSADMIN_PATH',
'/home/httpd/bscw/bin/bsadmin',
)
SAAS_GITLAB_ROOT_PASSWORD = Setting('SAAS_GITLAB_ROOT_PASSWORD',
'secret'
'secret',
)
SAAS_GITLAB_DOMAIN = Setting('SAAS_GITLAB_DOMAIN',
'gitlab.{}'.format(ORCHESTRA_BASE_DOMAIN)
'gitlab.{}'.format(ORCHESTRA_BASE_DOMAIN),
help_text="Uses <tt>ORCHESTRA_BASE_DOMAIN</tt> by default.",
)

View File

@ -3,7 +3,8 @@ from django.utils.translation import ugettext_lazy as _
from orchestra.settings import Setting
SERVICES_SERVICE_TAXES = Setting('SERVICES_SERVICE_TAXES', (
SERVICES_SERVICE_TAXES = Setting('SERVICES_SERVICE_TAXES',
(
(0, _("Duty free")),
(21, "21%"),
),
@ -11,31 +12,39 @@ SERVICES_SERVICE_TAXES = Setting('SERVICES_SERVICE_TAXES', (
)
SERVICES_SERVICE_DEFAULT_TAX = Setting('SERVICES_SERVICE_DEFAULT_TAX', 0,
SERVICES_SERVICE_DEFAULT_TAX = Setting('SERVICES_SERVICE_DEFAULT_TAX',
0,
choices=SERVICES_SERVICE_TAXES
)
SERVICES_SERVICE_ANUAL_BILLING_MONTH = Setting('SERVICES_SERVICE_ANUAL_BILLING_MONTH', 1,
SERVICES_SERVICE_ANUAL_BILLING_MONTH = Setting('SERVICES_SERVICE_ANUAL_BILLING_MONTH',
1,
choices=tuple((n, n) for n in range(1, 13))
)
SERVICES_ORDER_MODEL = Setting('SERVICES_ORDER_MODEL', 'orders.Order',
SERVICES_ORDER_MODEL = Setting('SERVICES_ORDER_MODEL',
'orders.Order',
validators=[Setting.validate_model_label]
)
SERVICES_RATE_CLASS = Setting('SERVICES_RATE_CLASS', 'orchestra.contrib.plans.models.Rate',
SERVICES_RATE_CLASS = Setting('SERVICES_RATE_CLASS',
'orchestra.contrib.plans.models.Rate',
validators=[Setting.validate_import_class]
)
SERVICES_DEFAULT_IGNORE_PERIOD = Setting('SERVICES_DEFAULT_IGNORE_PERIOD', 'TEN_DAYS')
SERVICES_DEFAULT_IGNORE_PERIOD = Setting('SERVICES_DEFAULT_IGNORE_PERIOD',
'TEN_DAYS'
)
SERVICES_IGNORE_ACCOUNT_TYPE = Setting('SERVICES_IGNORE_ACCOUNT_TYPE', (
'superuser',
'STAFF',
'FRIEND',
))
SERVICES_IGNORE_ACCOUNT_TYPE = Setting('SERVICES_IGNORE_ACCOUNT_TYPE',
(
'superuser',
'STAFF',
'FRIEND',
),
)

View File

@ -2,7 +2,7 @@ from functools import partial
from django.contrib import admin, messages
from django.db import models
from django.shortcuts import render_to_response
from django.views import generic
from django.utils.translation import ngettext, ugettext_lazy as _
@ -15,6 +15,7 @@ from .forms import SettingFormSet
class SettingView(generic.edit.FormView):
template_name = 'admin/settings/change_form.html'
reload_template_name = 'admin/settings/reload.html'
form_class = SettingFormSet
success_url = '.'
@ -71,13 +72,15 @@ class SettingView(generic.edit.FormView):
# Save changes
parser.save(changes)
n = len(changes)
messages.success(self.request, ngettext(
_("One change successfully applied, the orchestra is going to be restarted..."),
_("%s changes successfully applied, the orchestra is going to be restarted...") % n,
n)
)
sys.run('{ sleep 2 && touch %s/wsgi.py; } &' % paths.get_project_dir(), async=True)
n = len(changes)
context = {
'message': ngettext(
_("One change successfully applied, orchestra is being restarted."),
_("%s changes successfully applied, orchestra is being restarted.") % n,
n),
}
return render_to_response(self.reload_template_name, context)
else:
messages.success(self.request, _("No changes have been detected."))
return super(SettingView, self).form_valid(form)

View File

@ -33,6 +33,7 @@ class SettingForm(ReadOnlyFormMixin, forms.Form):
FORMFIELD_FOR_SETTING_TYPE = {
bool: partial(forms.BooleanField, required=False),
int: forms.IntegerField,
float: forms.FloatField,
tuple: TEXTAREA,
list: TEXTAREA,
dict: TEXTAREA,

View File

@ -79,7 +79,7 @@ def serialize(obj, init=True):
return nested
_obj.append(nested)
_obj = type(obj)(_obj)
elif isinstance(obj, (str, bool, int)):
elif isinstance(obj, (str, bool, int, float)):
_obj = obj
else:
_obj = NotSupported()
@ -132,7 +132,7 @@ def apply(changes, settings_file=get_settings_file()):
content.extend(comments)
inside = False
# insert new variables
# insert new variables at the end of file
for name, value in changes.items():
content.append(_format_setting(name, value))
return '\n'.join(content)

View File

@ -0,0 +1,54 @@
{% load staticfiles %}
<html>
<head>
<style>
.alert-box {
color:#555;
border-radius:10px;
font-family:Tahoma,Geneva,Arial,sans-serif;font-size:13px;
padding:10px 10px 10px 36px;
width: 500px;
height: 35px;
position: absolute;
top:0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
margin-top: 100px;
}
.alert-box span {
font-weight:bold;
text-transform:uppercase;
}
.warning {
background:#fff8c4 url('images/warning.png') no-repeat 10px 50%;
border:1px solid #f2c779;
}
</style>
<script src="{% static "admin/js/jquery.js" %}" type="text/javascript"></script>
<script>
function endCountdown() {
window.location.reload();
}
function handleTimer() {
if(count === 0) {
clearInterval(timer);
endCountdown();
} else {
$('#count_num').html(count);
count--;
}
}
var count = 4;
var timer = setInterval(function() { handleTimer(count); }, 1000);
</script>
</head>
<body>
<meta http-equiv="refresh" content="6">
<div>
<div class="alert-box warning"><span>notice: </span>{{ message }}<br> Refreshing in <span id="count_num">5</span></span>.</div>
</div>
</body>
</html>

View File

@ -3,7 +3,12 @@ from django.utils.translation import ugettext_lazy as _
from orchestra.settings import Setting
SYSTEMUSERS_SHELLS = Setting('SYSTEMUSERS_SHELLS', (
_names = ('user', 'username')
_backend_names = _names + ('group', 'shell', 'mainuser', 'home', 'base_home')
SYSTEMUSERS_SHELLS = Setting('SYSTEMUSERS_SHELLS',
(
('/dev/null', _("No shell, FTP only")),
('/bin/rssh', _("No shell, SFTP/RSYNC only")),
('/bin/bash', "/bin/bash"),
@ -13,7 +18,8 @@ SYSTEMUSERS_SHELLS = Setting('SYSTEMUSERS_SHELLS', (
)
SYSTEMUSERS_DEFAULT_SHELL = Setting('SYSTEMUSERS_DEFAULT_SHELL', '/dev/null',
SYSTEMUSERS_DEFAULT_SHELL = Setting('SYSTEMUSERS_DEFAULT_SHELL',
'/dev/null',
choices=SYSTEMUSERS_SHELLS
)
@ -27,7 +33,9 @@ SYSTEMUSERS_DISABLED_SHELLS = Setting('SYSTEMUSERS_DISABLED_SHELLS',
SYSTEMUSERS_HOME = Setting('SYSTEMUSERS_HOME',
'/home/%(user)s'
'/home/%(user)s',
help_text="Available fromat names: <tt>%s</tt>" % ', '.join(_names),
validators=[Setting.string_format_validator(_names)],
)
@ -46,5 +54,7 @@ SYSTEMUSERS_DEFAULT_GROUP_MEMBERS = Setting('SYSTEMUSERS_DEFAULT_GROUP_MEMBERS',
SYSTEMUSERS_MOVE_ON_DELETE_PATH = Setting('SYSTEMUSERS_MOVE_ON_DELETE_PATH',
''
'',
help_text="Available fromat names: <tt>%s</tt>" % ', '.join(_backend_names),
validators=[Setting.string_format_validator(_backend_names)],
)

View File

@ -1,21 +1,29 @@
from orchestra.settings import Setting
VPS_TYPES = Setting('VPS_TYPES', (
VPS_TYPES = Setting('VPS_TYPES',
(
('openvz', 'OpenVZ container'),
),
validators=[Setting.validate_choices]
)
VPS_DEFAULT_TYPE = Setting('VPS_DEFAULT_TYPE', 'openvz', choices=VPS_TYPES)
VPS_DEFAULT_TYPE = Setting('VPS_DEFAULT_TYPE',
'openvz',
choices=VPS_TYPES
)
VPS_TEMPLATES = Setting('VPS_TEMPLATES', (
VPS_TEMPLATES = Setting('VPS_TEMPLATES',
(
('debian7', 'Debian 7 - Wheezy'),
),
validators=[Setting.validate_choices]
)
VPS_DEFAULT_TEMPLATE = Setting('VPS_DEFAULT_TEMPLATE', 'debian7', choices=VPS_TEMPLATES)
VPS_DEFAULT_TEMPLATE = Setting('VPS_DEFAULT_TEMPLATE',
'debian7',
choices=VPS_TEMPLATES
)

View File

@ -45,7 +45,7 @@ class WebAppServiceMixin(object):
'user': webapp.get_username(),
'group': webapp.get_groupname(),
'app_name': webapp.name,
'type': webapp.type,
'app_type': webapp.type,
'app_path': webapp.get_path(),
'banner': self.get_banner(),
'under_construction_path': settings.WEBAPPS_UNDER_CONSTRUCTION_PATH,

View File

@ -3,14 +3,23 @@ from orchestra.settings import ORCHESTRA_BASE_DOMAIN, Setting
from .. import webapps
_names = ('home', 'user', 'group', 'app_type', 'app_name', 'app_type', 'app_id')
_php_names = _names + ('php_version', 'php_version_number',)
_python_names = _names + ('python_version', 'python_version_number',)
WEBAPPS_BASE_DIR = Setting('WEBAPPS_BASE_DIR',
'%(home)s/webapps/%(app_name)s'
'%(home)s/webapps/%(app_name)s',
help_text="Available fromat names: <tt>%s</tt>" % ', '.join(_names),
validators=[Setting.string_format_validator(_names)],
)
WEBAPPS_FPM_LISTEN = Setting('WEBAPPS_FPM_LISTEN',
# '127.0.0.1:9%(app_id)03d
'/opt/php/5.4/socks/%(user)s-%(app_name)s.sock'
'/opt/php/5.4/socks/%(user)s-%(app_name)s.sock',
help_text=("TCP socket example: <tt>127.0.0.1:9%(app_id)03d</tt><br>"
"Available fromat names: <tt>{}</tt>").format(', '.join(_php_names)),
validators=[Setting.string_format_validator(_php_names)],
)
@ -20,20 +29,25 @@ WEBAPPS_FPM_DEFAULT_MAX_CHILDREN = Setting('WEBAPPS_FPM_DEFAULT_MAX_CHILDREN',
WEBAPPS_PHPFPM_POOL_PATH = Setting('WEBAPPS_PHPFPM_POOL_PATH',
'/etc/php5/fpm/pool.d/%(user)s-%(app_name)s.conf'
'/etc/php5/fpm/pool.d/%(user)s-%(app_name)s.conf',
help_text="Available fromat names: <tt>%s</tt>" % ', '.join(_php_names),
validators=[Setting.string_format_validator(_php_names)],
)
WEBAPPS_FCGID_WRAPPER_PATH = Setting('WEBAPPS_FCGID_WRAPPER_PATH',
'/home/httpd/fcgi-bin.d/%(user)s/%(app_name)s-wrapper',
validators=[Setting.string_format_validator(_php_names)],
help_text=("Inside SuExec Document root.<br>"
"Make sure all account wrappers are in the same DIR.")
"Make sure all account wrappers are in the same DIR.<br>"
"Available fromat names: <tt>%s</tt>") % ', '.join(_php_names),
)
WEBAPPS_FCGID_CMD_OPTIONS_PATH = Setting('WEBAPPS_FCGID_CMD_OPTIONS_PATH',
'/etc/apache2/fcgid-conf/%(user)s-%(app_name)s.conf',
help_text="Loaded by Apache."
validators=[Setting.string_format_validator(_php_names)],
help_text="Loaded by Apache. Available fromat names: <tt>%s</tt>" % ', '.join(_php_names),
)
@ -43,7 +57,9 @@ WEBAPPS_PHP_MAX_REQUESTS = Setting('WEBAPPS_PHP_MAX_REQUESTS',
)
WEBAPPS_PHP_ERROR_LOG_PATH = Setting('WEBAPPS_PHP_ERROR_LOG_PATH', '')
WEBAPPS_PHP_ERROR_LOG_PATH = Setting('WEBAPPS_PHP_ERROR_LOG_PATH',
''
)
WEBAPPS_MERGE_PHP_WEBAPPS = Setting('WEBAPPS_MERGE_PHP_WEBAPPS',
@ -78,27 +94,35 @@ WEBAPPS_PHP_VERSIONS = Setting('WEBAPPS_PHP_VERSIONS', (
)
WEBAPPS_DEFAULT_PHP_VERSION = Setting('WEBAPPS_DEFAULT_PHP_VERSION', '5.4-cgi',
WEBAPPS_DEFAULT_PHP_VERSION = Setting('WEBAPPS_DEFAULT_PHP_VERSION',
'5.4-cgi',
choices=WEBAPPS_PHP_VERSIONS
)
WEBAPPS_PHP_CGI_BINARY_PATH = Setting('WEBAPPS_PHP_CGI_BINARY_PATH', '/usr/bin/php%(php_version_number)s-cgi',
help_text="Path of the cgi binary used by fcgid."
WEBAPPS_PHP_CGI_BINARY_PATH = Setting('WEBAPPS_PHP_CGI_BINARY_PATH',
'/usr/bin/php%(php_version_number)s-cgi',
help_text="Path of the cgi binary used by fcgid. Available fromat names: <tt>%s</tt>" % ', '.join(_php_names),
validators=[Setting.string_format_validator(_php_names)],
)
WEBAPPS_PHP_CGI_RC_DIR = Setting('WEBAPPS_PHP_CGI_RC_DIR', '/etc/php%(php_version_number)s/cgi/',
help_text="Path to php.ini."
WEBAPPS_PHP_CGI_RC_DIR = Setting('WEBAPPS_PHP_CGI_RC_DIR',
'/etc/php%(php_version_number)s/cgi/',
help_text="Path to php.ini. Available fromat names: <tt>%s</tt>" % ', '.join(_php_names),
validators=[Setting.string_format_validator(_php_names)],
)
WEBAPPS_PHP_CGI_INI_SCAN_DIR = Setting('WEBAPPS_PHP_CGI_INI_SCAN_DIR',
'/etc/php%(php_version_number)s/cgi/conf.d'
'/etc/php%(php_version_number)s/cgi/conf.d',
help_text="Available fromat names: <tt>%s</tt>" % ', '.join(_php_names),
validators=[Setting.string_format_validator(_php_names)],
)
WEBAPPS_PYTHON_VERSIONS = Setting('WEBAPPS_PYTHON_VERSIONS', (
WEBAPPS_PYTHON_VERSIONS = Setting('WEBAPPS_PYTHON_VERSIONS',
(
('3.4-uwsgi', 'Python 3.4 uWSGI'),
('2.7-uwsgi', 'Python 2.7 uWSGI'),
),
@ -106,13 +130,17 @@ WEBAPPS_PYTHON_VERSIONS = Setting('WEBAPPS_PYTHON_VERSIONS', (
)
WEBAPPS_DEFAULT_PYTHON_VERSION = Setting('WEBAPPS_DEFAULT_PYTHON_VERSION', '3.4-uwsgi',
WEBAPPS_DEFAULT_PYTHON_VERSION = Setting('WEBAPPS_DEFAULT_PYTHON_VERSION',
'3.4-uwsgi',
choices=WEBAPPS_PYTHON_VERSIONS
)
WEBAPPS_UWSGI_SOCKET = Setting('WEBAPPS_UWSGI_SOCKET',
'/var/run/uwsgi/app/%(app_name)s/socket'
'/var/run/uwsgi/app/%(app_name)s/socket',
help_text="Available fromat names: <tt>%s</tt>" % ', '.join(_python_names),
validators=[Setting.string_format_validator(_python_names)],
)
@ -218,7 +246,8 @@ WEBAPPS_ENABLED_OPTIONS = Setting('WEBAPPS_ENABLED_OPTIONS', (
WEBAPPS_DEFAULT_MYSQL_DATABASE_HOST = Setting('WEBAPPS_DEFAULT_MYSQL_DATABASE_HOST',
'mysql.{}'.format(ORCHESTRA_BASE_DOMAIN)
'mysql.{}'.format(ORCHESTRA_BASE_DOMAIN),
help_text="Uses <tt>ORCHESTRA_BASE_DOMAIN</tt> by default.",
)

View File

@ -94,11 +94,13 @@ class Website(models.Model):
def get_www_access_log_path(self):
context = self.get_settings_context()
context['unique_name'] = self.unique_name
path = settings.WEBSITES_WEBSITE_WWW_ACCESS_LOG_PATH % context
return os.path.normpath(path)
def get_www_error_log_path(self):
context = self.get_settings_context()
context['unique_name'] = self.unique_name
path = settings.WEBSITES_WEBSITE_WWW_ERROR_LOG_PATH % context
return os.path.normpath(path)

View File

@ -5,8 +5,14 @@ from orchestra.settings import Setting
from .. import websites
_names = ('id', 'pk', 'home', 'user', 'group', 'site_name', 'protocol')
_log_names = _names + ('unique_name',)
WEBSITES_UNIQUE_NAME_FORMAT = Setting('WEBSITES_UNIQUE_NAME_FORMAT',
default='%(user)s-%(site_name)s'
default='%(user)s-%(site_name)s',
help_text="Available fromat names: <tt>%s</tt>" % ', '.join(_names),
validators=[Setting.string_format_validator(_names)],
)
@ -69,12 +75,16 @@ WEBSITES_WEBALIZER_PATH = Setting('WEBSITES_WEBALIZER_PATH',
WEBSITES_WEBSITE_WWW_ACCESS_LOG_PATH = Setting('WEBSITES_WEBSITE_WWW_ACCESS_LOG_PATH',
'/var/log/apache2/virtual/%(unique_name)s.log'
'/var/log/apache2/virtual/%(unique_name)s.log',
help_text="Available fromat names: <tt>%s</tt>" % ', '.join(_log_names),
validators=[Setting.string_format_validator(_log_names)],
)
WEBSITES_WEBSITE_WWW_ERROR_LOG_PATH = Setting('WEBSITES_WEBSITE_WWW_ERROR_LOG_PATH',
''
'',
help_text="Available fromat names: <tt>%s</tt>" % ', '.join(_log_names),
validators=[Setting.string_format_validator(_log_names)],
)
@ -93,11 +103,13 @@ WEBSITES_TRAFFIC_IGNORE_HOSTS = Setting('WEBSITES_TRAFFIC_IGNORE_HOSTS',
# '')
WEBSITES_SAAS_DIRECTIVES = Setting('WEBSITES_SAAS_DIRECTIVES', {
'wordpress-saas': ('fpm', '/opt/php/5.4/socks/pangea.sock', '/home/httpd/wordpress-mu/'),
'drupal-saas': ('fpm', '/opt/php/5.4/socks/pangea.sock','/home/httpd/drupal-mu/'),
'dokuwiki-saas': ('fpm', '/opt/php/5.4/socks/pangea.sock','/home/httpd/moodle-mu/'),
})
WEBSITES_SAAS_DIRECTIVES = Setting('WEBSITES_SAAS_DIRECTIVES',
{
'wordpress-saas': ('fpm', '/opt/php/5.4/socks/pangea.sock', '/home/httpd/wordpress-mu/'),
'drupal-saas': ('fpm', '/opt/php/5.4/socks/pangea.sock','/home/httpd/drupal-mu/'),
'dokuwiki-saas': ('fpm', '/opt/php/5.4/socks/pangea.sock','/home/httpd/moodle-mu/'),
},
)
WEBSITES_DEFAULT_SSL_CERT = Setting('WEBSITES_DEFAULT_SSL_CERT',
@ -112,7 +124,8 @@ WEBSITES_DEFAULT_SSL_CA = Setting('WEBSITES_DEFAULT_SSL_CA',
''
)
WEBSITES_VHOST_EXTRA_DIRECTIVES = Setting('WEBSITES_VHOST_EXTRA_DIRECTIVES', (),
WEBSITES_VHOST_EXTRA_DIRECTIVES = Setting('WEBSITES_VHOST_EXTRA_DIRECTIVES',
(),
help_text=(
"(<location>, <directive>), <br>"
"i.e. ('/cgi-bin/', 'ScriptAlias /cgi-bin/ %(home)s/cgi-bin/')"

View File

@ -1,10 +1,11 @@
import textwrap
from optparse import make_option
from os.path import expanduser
from django.conf import settings
from django.core.management.base import BaseCommand
from orchestra.utils.paths import get_project_dir, get_site_dir, get_project_name
from orchestra.utils import paths
from orchestra.utils.sys import run, check_root, get_default_celeryd_username
@ -32,44 +33,49 @@ class Command(BaseCommand):
interactive = options.get('interactive')
context = {
'project_name': get_project_name(),
'project_dir': get_project_dir(),
'site_dir': get_site_dir(),
'project_name': paths.get_project_name(),
'project_dir': paths.get_project_dir(),
'site_dir': paths.get_site_dir(),
'static_root': settings.STATIC_ROOT,
'user': options.get('user'),
'group': options.get('group') or options.get('user'),
'home': expanduser("~%s" % options.get('user')),
'processes': int(options.get('processes')),}
nginx_conf = (
'server {\n'
' listen 80;\n'
' listen [::]:80 ipv6only=on;\n'
' rewrite ^/$ /admin/;\n'
' client_max_body_size 500m;\n'
' location / {\n'
' uwsgi_pass unix:///var/run/uwsgi/app/%(project_name)s/socket;\n'
' include uwsgi_params;\n'
' }\n'
' location /static {\n'
' alias %(static_root)s;\n'
' expires 30d;\n'
' }\n'
'}\n') % context
nginx_conf = textwrap.dedent("""\
server {
listen 80;
listen [::]:80 ipv6only=on;
rewrite ^/$ /admin/;
client_max_body_size 500m;
location / {
uwsgi_pass unix:///var/run/uwsgi/app/%(project_name)s/socket;
include uwsgi_params;
}
location /static {
alias %(static_root)s;
expires 30d;
}
}
"""
) % context
uwsgi_conf = (
'[uwsgi]\n'
'plugins = python\n'
'chdir = %(site_dir)s\n'
'module = %(project_name)s.wsgi\n'
'master = true\n'
'processes = %(processes)d\n'
'chmod-socket = 664\n'
'stats = /run/uwsgi/%%(deb-confnamespace)/%%(deb-confname)/statsocket\n'
'vacuum = true\n'
'uid = %(user)s\n'
'gid = %(group)s\n'
'env = HOME=%(home)s\n') % context
uwsgi_conf = textwrap.dedent("""\
[uwsgi]
plugins = python
chdir = %(site_dir)s
module = %(project_name)s.wsgi
master = true
processes = %(processes)d
chmod-socket = 664
stats = /run/uwsgi/%%(deb-confnamespace)/%%(deb-confname)/statsocket
vacuum = true
uid = %(user)s
gid = %(group)s
env = HOME=%(home)s
touch-reload = %(project_dir)s/wsgi.py
"""
) % context
nginx = {
'file': '/etc/nginx/conf.d/%(project_name)s.conf' % context,
@ -108,20 +114,21 @@ class Command(BaseCommand):
current = "\$local_fs \$remote_fs \$network \$syslog"
run('sed -i "s/ %s$/ %s \$named/g" /etc/init.d/nginx' % (current, current))
rotate = (
'/var/log/nginx/*.log {\n'
' daily\n'
' missingok\n'
' rotate 30\n'
' compress\n'
' delaycompress\n'
' notifempty\n'
' create 640 root adm\n'
' sharedscripts\n'
' postrotate\n'
' [ ! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.pid`\n'
' endscript\n'
'}\n')
rotate = textwrap.dedent("""\
/var/log/nginx/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 640 root adm
sharedscripts
postrotate
[ ! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.pid`
endscript
}"""
)
run("echo '%s' > /etc/logrotate.d/nginx" % rotate)
# Allow nginx to write to uwsgi socket

View File

@ -4,6 +4,7 @@ from collections import OrderedDict
from django.conf import settings
from django.core.exceptions import ValidationError, AppRegistryNotReady
from django.core.validators import validate_email
from django.db.models import get_model
from django.utils.functional import Promise
from django.utils.translation import ugettext_lazy as _
@ -127,7 +128,8 @@ ORCHESTRA_BASE_DOMAIN = Setting('ORCHESTRA_BASE_DOMAIN',
ORCHESTRA_SITE_URL = Setting('ORCHESTRA_SITE_URL',
'https://orchestra.%s' % ORCHESTRA_BASE_DOMAIN,
help_text=_("Domain name used when it will not be possible to infere the domain from a request."
"For example in periodic tasks.")
"For example in periodic tasks.<br>"
"Uses <tt>ORCHESTRA_BASE_DOMAIN</tt> by default.")
)
@ -137,7 +139,8 @@ ORCHESTRA_SITE_NAME = Setting('ORCHESTRA_SITE_NAME',
ORCHESTRA_SITE_VERBOSE_NAME = Setting('ORCHESTRA_SITE_VERBOSE_NAME',
_("%s Hosting Management" % ORCHESTRA_SITE_NAME.capitalize()),
"%s Hosting Management" % ORCHESTRA_SITE_NAME.capitalize(),
help_text="Uses <tt>ORCHESTRA_SITE_NAME</tt> by default."
)
@ -180,7 +183,9 @@ ORCHESTRA_API_ROOT_VIEW = Setting('ORCHESTRA_API_ROOT_VIEW',
ORCHESTRA_DEFAULT_SUPPORT_FROM_EMAIL = Setting('ORCHESTRA_DEFAULT_SUPPORT_FROM_EMAIL',
'support@{}'.format(ORCHESTRA_BASE_DOMAIN)
'support@{}'.format(ORCHESTRA_BASE_DOMAIN),
validators=[validate_email],
help_text="Uses <tt>ORCHESTRA_BASE_DOMAIN</tt> by default."
)

View File

@ -46,7 +46,7 @@
{% endif %}
<ul id="navigation-menu">
<div style="max-width: 1170px; margin:auto;">
<div id="branding"><a href="/admin/"></a><h1 id="site-name"><a href="/admin/">Pangea Hosting Management <span class="version">0.0.1a1</span></a></h1></div>
<div id="branding"><a href="/admin/"></a><h1 id="site-name"><a href="/admin/">{{ SITE_VERBOSE_NAME }}<span class="version">0.0.1a1</span></a></h1></div>
{% for item in menu.children %}{% admin_tools_render_menu_item item forloop.counter %}{% endfor %}
<span style="float:right;color:grey;padding:10px;font-size:11px;">{% trans 'Welcome' %},
{% url 'admin:accounts_account_change' user.pk as user_change_url %}