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 # bill confirmation: show total
# Amend lines??? # Amend lines???
# orders currency setting
# Determine the difference between data serializer used for validation and used for the rest API! # 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 # 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 from orchestra.settings import ORCHESTRA_BASE_DOMAIN, Setting
ACCOUNTS_TYPES = Setting('ACCOUNTS_TYPES', ( ACCOUNTS_TYPES = Setting('ACCOUNTS_TYPES',
(
('INDIVIDUAL', _("Individual")), ('INDIVIDUAL', _("Individual")),
('ASSOCIATION', _("Association")), ('ASSOCIATION', _("Association")),
('CUSTOMER', _("Customer")), ('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')), ('EN', _('English')),
), ),
validators=[Setting.validate_choices] 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], 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', ( ACCOUNTS_CREATE_RELATED = Setting('ACCOUNTS_CREATE_RELATED',
# <model>, <key field>, <kwargs>, <help_text> (
('mailboxes.Mailbox', # <model>, <key field>, <kwargs>, <help_text>
'name', ('mailboxes.Mailbox',
{ 'name',
'name': 'account.username', {
'password': 'account.password', 'name': 'account.username',
}, 'password': 'account.password',
_("Designates whether to creates a related mailbox with the same name and password or not."), },
_("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', 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 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', 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] 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 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 choices=BILLS_CONTACT_COUNTRIES
) )

View File

@ -1,7 +1,10 @@
from orchestra.core.validators import validate_hostname
from orchestra.settings import Setting from orchestra.settings import Setting
DATABASES_TYPE_CHOICES = Setting('DATABASES_TYPE_CHOICES', ( DATABASES_TYPE_CHOICES = Setting('DATABASES_TYPE_CHOICES',
(
('mysql', 'MySQL'), ('mysql', 'MySQL'),
('postgres', 'PostgreSQL'), ('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 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', 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', 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', DOMAINS_DEFAULT_TTL = Setting('DOMAINS_DEFAULT_TTL',
'1h' '1h',
validators=[validate_zone_interval],
) )
DOMAINS_DEFAULT_REFRESH = Setting('DOMAINS_DEFAULT_REFRESH', DOMAINS_DEFAULT_REFRESH = Setting('DOMAINS_DEFAULT_REFRESH',
'1d' '1d',
validators=[validate_zone_interval],
) )
DOMAINS_DEFAULT_RETRY = Setting('DOMAINS_DEFAULT_RETRY', DOMAINS_DEFAULT_RETRY = Setting('DOMAINS_DEFAULT_RETRY',
'2h' '2h',
validators=[validate_zone_interval],
) )
DOMAINS_DEFAULT_EXPIRATION = Setting('DOMAINS_DEFAULT_EXPIRATION', DOMAINS_DEFAULT_EXPIRATION = Setting('DOMAINS_DEFAULT_EXPIRATION',
'4w' '4w',
validators=[validate_zone_interval],
) )
DOMAINS_DEFAULT_MIN_CACHING_TIME = Setting('DOMAINS_DEFAULT_MIN_CACHING_TIME', 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', DOMAINS_MASTERS_PATH = Setting('DOMAINS_MASTERS_PATH',
'/etc/bind/named.conf.local' '/etc/bind/named.conf.local',
) )
DOMAINS_SLAVES_PATH = Setting('DOMAINS_SLAVES_PATH', 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', 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] validators=[validate_ipv4_address]
) )
@ -73,19 +84,28 @@ DOMAINS_DEFAULT_AAAA = Setting('DOMAINS_DEFAULT_AAAA', '',
) )
DOMAINS_DEFAULT_MX = Setting('DOMAINS_DEFAULT_MX', ( DOMAINS_DEFAULT_MX = Setting('DOMAINS_DEFAULT_MX',
'10 mail.{}.'.format(ORCHESTRA_BASE_DOMAIN), default=(
'10 mail2.{}.'.format(ORCHESTRA_BASE_DOMAIN), '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', ( DOMAINS_DEFAULT_NS = Setting('DOMAINS_DEFAULT_NS',
'ns1.{}.'.format(ORCHESTRA_BASE_DOMAIN), default=(
'ns2.{}.'.format(ORCHESTRA_BASE_DOMAIN), '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=( help_text=(
"This setting prevents users from providing random domain names, i.e. google.com<br>" "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>" "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', 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()." help_text="Additional master server ip addresses other than autodiscovered by router.get_servers()."
) )
DOMAINS_SLAVES = Setting('DOMAINS_SLAVES', 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()." 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 import paths
from orchestra.utils.sys import run from orchestra.utils.sys import run
from . import settings from .. import domains
def validate_allowed_domain(value): def validate_allowed_domain(value):
context = { context = {
'site_dir': paths.get_site_dir() 'site_dir': paths.get_site_dir()
} }
fname = settings.DOMAINS_FORBIDDEN fname = domains.settings.DOMAINS_FORBIDDEN
if fname: if fname:
fname = fname % context fname = fname % context
with open(fname, 'r') as forbidden: with open(fname, 'r') as forbidden:
@ -108,8 +108,8 @@ def validate_soa_record(value):
def validate_zone(zone): def validate_zone(zone):
""" Ultimate zone file validation using named-checkzone """ """ Ultimate zone file validation using named-checkzone """
zone_name = zone.split()[0][:-1] zone_name = zone.split()[0][:-1]
zone_path = os.path.join(settings.DOMAINS_ZONE_VALIDATION_TMP_DIR, zone_name) zone_path = os.path.join(domains.settings.DOMAINS_ZONE_VALIDATION_TMP_DIR, zone_name)
checkzone = settings.DOMAINS_CHECKZONE_BIN_PATH checkzone = domains.settings.DOMAINS_CHECKZONE_BIN_PATH
try: try:
with open(zone_path, 'wb') as f: with open(zone_path, 'wb') as f:
f.write(zone.encode('ascii')) f.write(zone.encode('ascii'))

View File

@ -1,7 +1,11 @@
from orchestra.settings import Setting 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 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] validators=[Setting.validate_model_label]
) )
LISTS_DEFAULT_DOMAIN = Setting('LISTS_DEFAULT_DOMAIN', 'lists.{}'.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_LIST_URL = Setting('LISTS_LIST_URL',
'https://lists.{}/mailman/listinfo/%(name)s'.format(ORCHESTRA_BASE_DOMAIN)
) )
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 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', MAILBOXES_DOMAIN_MODEL = Setting('MAILBOXES_DOMAIN_MODEL', 'domains.Domain',
validators=[Setting.validate_model_label] 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', 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',))] 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, MAILBOXES_LOCAL_DOMAIN = Setting('MAILBOXES_LOCAL_DOMAIN',
validators=[validate_name] 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', { MAILBOXES_MAILBOX_FILTERINGS = Setting('MAILBOXES_MAILBOX_FILTERINGS',
# value: (verbose_name, filter) {
'DISABLE': (_("Disable"), ''), # value: (verbose_name, filter)
'REJECT': (_("Reject spam"), textwrap.dedent(""" 'DISABLE': (_("Disable"), ''),
require ["fileinto","regex","envelope","vacation","reject","relational","comparator-i;ascii-numeric"]; 'REJECT': (_("Reject spam"), textwrap.dedent("""
if header :value "ge" :comparator "i;ascii-numeric" "X-Spam-Score" "5" { require ["fileinto","regex","envelope","vacation","reject","relational","comparator-i;ascii-numeric"];
discard; if header :value "ge" :comparator "i;ascii-numeric" "X-Spam-Score" "5" {
stop; discard;
}""")), stop;
'REDIRECT': (_("Archive spam"), textwrap.dedent(""" }""")),
require ["fileinto","regex","envelope","vacation","reject","relational","comparator-i;ascii-numeric"]; 'REDIRECT': (_("Archive spam"), textwrap.dedent("""
if header :value "ge" :comparator "i;ascii-numeric" "X-Spam-Score" "5" { require ["fileinto","regex","envelope","vacation","reject","relational","comparator-i;ascii-numeric"];
fileinto "Spam"; if header :value "ge" :comparator "i;ascii-numeric" "X-Spam-Score" "5" {
stop; fileinto "Spam";
}""")), stop;
'CUSTOM': (_("Custom filtering"), lambda mailbox: mailbox.custom_filtering), }""")),
}) '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()) 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_MAILDIRSIZE_PATH = Setting('MAILBOXES_MAILDIRSIZE_PATH',
'%(home)s/Maildir/maildirsize',
help_text="Available fromat names: <tt>%s</tt>" % ', '.join(_backend_names),
MAILBOXES_LOCAL_ADDRESS_DOMAIN = Setting('MAILBOXES_LOCAL_ADDRESS_DOMAIN', ORCHESTRA_BASE_DOMAIN, validators=[Setting.string_format_validator(_backend_names)],
validators=[validate_name]
) )
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.contrib.accounts.admin import AccountAdminMixin
from orchestra.plugins import PluginModelAdapter from orchestra.plugins import PluginModelAdapter
from orchestra.plugins.admin import SelectPluginAdminMixin from orchestra.plugins.admin import SelectPluginAdminMixin
from orchestra.utils.python import import_class
from . import settings from . import settings
from .models import MiscService, Miscellaneous from .models import MiscService, Miscellaneous
@ -92,7 +93,8 @@ class MiscellaneousAdmin(AccountAdminMixin, SelectPluginAdminMixin, admin.ModelA
service = self.get_service(obj) service = self.get_service(obj)
def clean_identifier(self, service=service): def clean_identifier(self, service=service):
identifier = self.cleaned_data['identifier'] 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: if validator:
validator(identifier) validator(identifier)
return identifier return identifier

View File

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

View File

@ -1,35 +1,43 @@
from datetime import timedelta
from os import path from os import path
from orchestra.settings import Setting from orchestra.settings import Setting
ORCHESTRATION_OS_CHOICES = Setting('ORCHESTRATION_OS_CHOICES', ( ORCHESTRATION_OS_CHOICES = Setting('ORCHESTRATION_OS_CHOICES',
(
('LINUX', "Linux"), ('LINUX', "Linux"),
), ),
validators=[Setting.validate_choices] validators=[Setting.validate_choices]
) )
ORCHESTRATION_DEFAULT_OS = Setting('ORCHESTRATION_DEFAULT_OS', 'LINUX', ORCHESTRATION_DEFAULT_OS = Setting('ORCHESTRATION_DEFAULT_OS',
choices=ORCHESTRATION_OS_CHOICES) 'LINUX',
choices=ORCHESTRATION_OS_CHOICES
)
ORCHESTRATION_SSH_KEY_PATH = Setting('ORCHESTRATION_SSH_KEY_PATH', 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] validators=[Setting.validate_import_class]
) )
ORCHESTRATION_TEMP_SCRIPT_DIR = Setting('ORCHESTRATION_TEMP_SCRIPT_DIR', '/dev/shm') ORCHESTRATION_TEMP_SCRIPT_DIR = Setting('ORCHESTRATION_TEMP_SCRIPT_DIR',
'/dev/shm'
)
ORCHESTRATION_DISABLE_EXECUTION = Setting('ORCHESTRATION_DISABLE_EXECUTION', False)
ORCHESTRATION_DISABLE_EXECUTION = Setting('ORCHESTRATION_DISABLE_EXECUTION',
ORCHESTRATION_BACKEND_CLEANUP_DELTA = Setting('ORCHESTRATION_BACKEND_CLEANUP_DELTA', False
timedelta(days=15) )
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.task.schedules import crontab
from celery.decorators import periodic_task from celery.decorators import periodic_task
from django.utils import timezone 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)) @periodic_task(run_every=crontab(hour=7, minute=30, day_of_week=1))
def backend_logs_cleanup(run_every=run_every): 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() BackendLog.objects.filter(created_at__lt=epoch).delete()

View File

@ -1,19 +1,22 @@
from orchestra.settings import Setting 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], validators=[Setting.validate_import_class],
help_text="Pluggable backend for bill generation.", 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], 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', 'orders',
'admin', 'admin',
'contenttypes', '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>" 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 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.sepadirectdebit.SEPADirectDebit',
'orchestra.contrib.payments.methods.creditcard.CreditCard', 'orchestra.contrib.payments.methods.creditcard.CreditCard',
), ),

View File

@ -3,7 +3,8 @@ from orchestra.settings import ORCHESTRA_BASE_DOMAIN, Setting
from .. import saas 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.moodle.MoodleService',
'orchestra.contrib.saas.services.bscw.BSCWService', 'orchestra.contrib.saas.services.bscw.BSCWService',
'orchestra.contrib.saas.services.gitlab.GitLabService', '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', 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', 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', SAAS_PHPLIST_DB_NAME = Setting('SAAS_PHPLIST_DB_NAME',
'phplist_mu' 'phplist_mu',
) )
SAAS_PHPLIST_BASE_DOMAIN = Setting('SAAS_PHPLIST_BASE_DOMAIN', 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', 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', 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', SAAS_BSCW_DEFAULT_QUOTA = Setting('SAAS_BSCW_DEFAULT_QUOTA',
50 50,
) )
SAAS_BSCW_BSADMIN_PATH = Setting('SAAS_BSCW_BSADMIN_PATH', SAAS_BSCW_BSADMIN_PATH = Setting('SAAS_BSCW_BSADMIN_PATH',
'/home/httpd/bscw/bin/bsadmin', '/home/httpd/bscw/bin/bsadmin',
) )
SAAS_GITLAB_ROOT_PASSWORD = Setting('SAAS_GITLAB_ROOT_PASSWORD', SAAS_GITLAB_ROOT_PASSWORD = Setting('SAAS_GITLAB_ROOT_PASSWORD',
'secret' 'secret',
) )
SAAS_GITLAB_DOMAIN = Setting('SAAS_GITLAB_DOMAIN', 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 from orchestra.settings import Setting
SERVICES_SERVICE_TAXES = Setting('SERVICES_SERVICE_TAXES', ( SERVICES_SERVICE_TAXES = Setting('SERVICES_SERVICE_TAXES',
(
(0, _("Duty free")), (0, _("Duty free")),
(21, "21%"), (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 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)) 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] 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] 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', ( SERVICES_IGNORE_ACCOUNT_TYPE = Setting('SERVICES_IGNORE_ACCOUNT_TYPE',
'superuser', (
'STAFF', 'superuser',
'FRIEND', 'STAFF',
)) 'FRIEND',
),
)

View File

@ -2,7 +2,7 @@ from functools import partial
from django.contrib import admin, messages from django.contrib import admin, messages
from django.db import models from django.db import models
from django.shortcuts import render_to_response
from django.views import generic from django.views import generic
from django.utils.translation import ngettext, ugettext_lazy as _ from django.utils.translation import ngettext, ugettext_lazy as _
@ -15,6 +15,7 @@ from .forms import SettingFormSet
class SettingView(generic.edit.FormView): class SettingView(generic.edit.FormView):
template_name = 'admin/settings/change_form.html' template_name = 'admin/settings/change_form.html'
reload_template_name = 'admin/settings/reload.html'
form_class = SettingFormSet form_class = SettingFormSet
success_url = '.' success_url = '.'
@ -71,13 +72,15 @@ class SettingView(generic.edit.FormView):
# Save changes # Save changes
parser.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) 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: else:
messages.success(self.request, _("No changes have been detected.")) messages.success(self.request, _("No changes have been detected."))
return super(SettingView, self).form_valid(form) return super(SettingView, self).form_valid(form)

View File

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

View File

@ -79,7 +79,7 @@ def serialize(obj, init=True):
return nested return nested
_obj.append(nested) _obj.append(nested)
_obj = type(obj)(_obj) _obj = type(obj)(_obj)
elif isinstance(obj, (str, bool, int)): elif isinstance(obj, (str, bool, int, float)):
_obj = obj _obj = obj
else: else:
_obj = NotSupported() _obj = NotSupported()
@ -131,8 +131,8 @@ def apply(changes, settings_file=get_settings_file()):
if num == lastend: if num == lastend:
content.extend(comments) content.extend(comments)
inside = False inside = False
# insert new variables # 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)

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 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")), ('/dev/null', _("No shell, FTP only")),
('/bin/rssh', _("No shell, SFTP/RSYNC only")), ('/bin/rssh', _("No shell, SFTP/RSYNC only")),
('/bin/bash', "/bin/bash"), ('/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 choices=SYSTEMUSERS_SHELLS
) )
@ -27,7 +33,9 @@ SYSTEMUSERS_DISABLED_SHELLS = Setting('SYSTEMUSERS_DISABLED_SHELLS',
SYSTEMUSERS_HOME = Setting('SYSTEMUSERS_HOME', 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', 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 from orchestra.settings import Setting
VPS_TYPES = Setting('VPS_TYPES', ( VPS_TYPES = Setting('VPS_TYPES',
(
('openvz', 'OpenVZ container'), ('openvz', 'OpenVZ container'),
), ),
validators=[Setting.validate_choices] 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'), ('debian7', 'Debian 7 - Wheezy'),
), ),
validators=[Setting.validate_choices] 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(), 'user': webapp.get_username(),
'group': webapp.get_groupname(), 'group': webapp.get_groupname(),
'app_name': webapp.name, 'app_name': webapp.name,
'type': webapp.type, 'app_type': webapp.type,
'app_path': webapp.get_path(), 'app_path': webapp.get_path(),
'banner': self.get_banner(), 'banner': self.get_banner(),
'under_construction_path': settings.WEBAPPS_UNDER_CONSTRUCTION_PATH, '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 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', 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', 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', 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', WEBAPPS_FCGID_WRAPPER_PATH = Setting('WEBAPPS_FCGID_WRAPPER_PATH',
'/home/httpd/fcgi-bin.d/%(user)s/%(app_name)s-wrapper', '/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>" 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', WEBAPPS_FCGID_CMD_OPTIONS_PATH = Setting('WEBAPPS_FCGID_CMD_OPTIONS_PATH',
'/etc/apache2/fcgid-conf/%(user)s-%(app_name)s.conf', '/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', 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 choices=WEBAPPS_PHP_VERSIONS
) )
WEBAPPS_PHP_CGI_BINARY_PATH = Setting('WEBAPPS_PHP_CGI_BINARY_PATH', '/usr/bin/php%(php_version_number)s-cgi', WEBAPPS_PHP_CGI_BINARY_PATH = Setting('WEBAPPS_PHP_CGI_BINARY_PATH',
help_text="Path of the cgi binary used by fcgid." '/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/', WEBAPPS_PHP_CGI_RC_DIR = Setting('WEBAPPS_PHP_CGI_RC_DIR',
help_text="Path to php.ini." '/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', 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'), ('3.4-uwsgi', 'Python 3.4 uWSGI'),
('2.7-uwsgi', 'Python 2.7 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 choices=WEBAPPS_PYTHON_VERSIONS
) )
WEBAPPS_UWSGI_SOCKET = Setting('WEBAPPS_UWSGI_SOCKET', 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', 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): def get_www_access_log_path(self):
context = self.get_settings_context() context = self.get_settings_context()
context['unique_name'] = self.unique_name
path = settings.WEBSITES_WEBSITE_WWW_ACCESS_LOG_PATH % context path = settings.WEBSITES_WEBSITE_WWW_ACCESS_LOG_PATH % context
return os.path.normpath(path) return os.path.normpath(path)
def get_www_error_log_path(self): def get_www_error_log_path(self):
context = self.get_settings_context() context = self.get_settings_context()
context['unique_name'] = self.unique_name
path = settings.WEBSITES_WEBSITE_WWW_ERROR_LOG_PATH % context path = settings.WEBSITES_WEBSITE_WWW_ERROR_LOG_PATH % context
return os.path.normpath(path) return os.path.normpath(path)

View File

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

View File

@ -4,6 +4,7 @@ from collections import OrderedDict
from django.conf import settings from django.conf import settings
from django.core.exceptions import ValidationError, AppRegistryNotReady from django.core.exceptions import ValidationError, AppRegistryNotReady
from django.core.validators import validate_email
from django.db.models import get_model from django.db.models import get_model
from django.utils.functional import Promise from django.utils.functional import Promise
from django.utils.translation import ugettext_lazy as _ 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', ORCHESTRA_SITE_URL = Setting('ORCHESTRA_SITE_URL',
'https://orchestra.%s' % ORCHESTRA_BASE_DOMAIN, 'https://orchestra.%s' % ORCHESTRA_BASE_DOMAIN,
help_text=_("Domain name used when it will not be possible to infere the domain from a request." 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', 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', 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 %} {% endif %}
<ul id="navigation-menu"> <ul id="navigation-menu">
<div style="max-width: 1170px; margin:auto;"> <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 %} {% 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' %}, <span style="float:right;color:grey;padding:10px;font-size:11px;">{% trans 'Welcome' %},
{% url 'admin:accounts_account_change' user.pk as user_change_url %} {% url 'admin:accounts_account_change' user.pk as user_change_url %}