Added help text on webapps and websites options

This commit is contained in:
Marc Aymerich 2014-11-10 15:03:34 +00:00
parent f9c6a5b9cc
commit f4ca49b912
7 changed files with 247 additions and 165 deletions

View file

@ -7,6 +7,7 @@ from orchestra.admin import ExtendedModelAdmin
from orchestra.admin.utils import change_url from orchestra.admin.utils import change_url
from orchestra.apps.accounts.admin import AccountAdminMixin from orchestra.apps.accounts.admin import AccountAdminMixin
from . import settings
from .models import WebApp, WebAppOption from .models import WebApp, WebAppOption
@ -14,6 +15,11 @@ class WebAppOptionInline(admin.TabularInline):
model = WebAppOption model = WebAppOption
extra = 1 extra = 1
OPTIONS_HELP_TEXT = str({
k: str(unicode(v[1])) if len(v) == 3 else ''
for k, v in settings.WEBAPPS_OPTIONS.iteritems()
})
class Media: class Media:
css = { css = {
'all': ('orchestra/css/hide-inline-id.css',) 'all': ('orchestra/css/hide-inline-id.css',)
@ -23,6 +29,17 @@ class WebAppOptionInline(admin.TabularInline):
""" Make value input widget bigger """ """ Make value input widget bigger """
if db_field.name == 'value': if db_field.name == 'value':
kwargs['widget'] = forms.TextInput(attrs={'size':'100'}) kwargs['widget'] = forms.TextInput(attrs={'size':'100'})
if db_field.name == 'name':
kwargs['widget'] = forms.Select(attrs={
'onChange': """
siteoptions = %s;
valueelement = $("#"+this.id.replace("name", "value"));
valueelement.parent().find('p').remove();
valueelement.parent().append(
"<p class='help'>" + siteoptions[this.options[this.selectedIndex].value] + "</p>"
);
""" % self.OPTIONS_HELP_TEXT,
})
return super(WebAppOptionInline, self).formfield_for_dbfield(db_field, **kwargs) return super(WebAppOptionInline, self).formfield_for_dbfield(db_field, **kwargs)

View file

@ -78,7 +78,7 @@ class WebAppOption(models.Model):
def clean(self): def clean(self):
""" validates name and value according to WEBAPPS_OPTIONS """ """ validates name and value according to WEBAPPS_OPTIONS """
__, regex = settings.WEBAPPS_OPTIONS[self.name] regex = settings.WEBAPPS_OPTIONS[self.name][-1]
if not re.match(regex, self.value): if not re.match(regex, self.value):
raise ValidationError({ raise ValidationError({
'value': ValidationError(_("'%(value)s' does not match %(regex)s."), 'value': ValidationError(_("'%(value)s' does not match %(regex)s."),

View file

@ -77,153 +77,6 @@ WEBAPPS_DEFAULT_HTTPS_CERT = getattr(settings, 'WEBAPPS_DEFAULT_HTTPS_CERT',
) )
WEBAPPS_OPTIONS = getattr(settings, 'WEBAPPS_OPTIONS', {
# { name: ( verbose_name, validation_regex ) }
# PHP
'enabled_functions': (
_("PHP - Enabled functions"),
r'^[\w\.,-]+$'
),
'PHP-allow_url_include': (
_("PHP - Allow URL include"),
r'^(On|Off|on|off)$'
),
'PHP-allow_url_fopen': (
_("PHP - allow_url_fopen"),
r'^(On|Off|on|off)$'
),
'PHP-auto_append_file': (
_("PHP - Auto append file"),
r'^[\w\.,-/]+$'
),
'PHP-auto_prepend_file': (
_("PHP - Auto prepend file"),
r'^[\w\.,-/]+$'
),
'PHP-date.timezone': (
_("PHP - date.timezone"),
r'^\w+/\w+$'
),
'PHP-default_socket_timeout': (
_("PHP - Default socket timeout"),
r'^[0-9]{1,3}$'
),
'PHP-display_errors': (
_("PHP - Display errors"),
r'^(On|Off|on|off)$'
),
'PHP-extension': (
_("PHP - Extension"),
r'^[^ ]+$'
),
'PHP-magic_quotes_gpc': (
_("PHP - Magic quotes GPC"),
r'^(On|Off|on|off)$'
),
'PHP-magic_quotes_runtime': (
_("PHP - Magic quotes runtime"),
r'^(On|Off|on|off)$'
),
'PHP-magic_quotes_sybase': (
_("PHP - Magic quotes sybase"),
r'^(On|Off|on|off)$'
),
'PHP-max_execution_time': (
_("PHP - Max execution time"),
r'^[0-9]{1,3}$'
),
'PHP-max_input_time': (
_("PHP - Max input time"),
r'^[0-9]{1,3}$'
),
'PHP-memory_limit': (
_("PHP - Memory limit"),
r'^[0-9]{1,3}M$'
),
'PHP-mysql.connect_timeout': (
_("PHP - Mysql connect timeout"),
r'^([0-9]){1,3}$'
),
'PHP-output_buffering': (
_("PHP - output_buffering"),
r'^(On|Off|on|off)$'
),
'PHP-register_globals': (
_("PHP - Register globals"),
r'^(On|Off|on|off)$'
),
'PHP-post_max_size': (
_("PHP - Post max size"),
r'^[0-9]{1,3}M$'
),
'PHP-sendmail_path': (
_("PHP - sendmail_path"),
r'^[^ ]+$'
),
'PHP-session.bug_compat_warn': (
_("PHP - session.bug_compat_warn"),
r'^(On|Off|on|off)$'
),
'PHP-session.auto_start': (
_("PHP - session.auto_start"),
r'^(On|Off|on|off)$'
),
'PHP-safe_mode': (
_("PHP - Safe mode"),
r'^(On|Off|on|off)$'
),
'PHP-suhosin.post.max_vars': (
_("PHP - Suhosin post max vars"),
r'^[0-9]{1,4}$'
),
'PHP-suhosin.request.max_vars': (
_("PHP - Suhosin request max vars"),
r'^[0-9]{1,4}$'
),
'PHP-suhosin.session.encrypt': (
_("PHP - suhosin.session.encrypt"),
r'^(On|Off|on|off)$'
),
'PHP-suhosin.simulation': (
_("PHP - Suhosin simulation"),
r'^(On|Off|on|off)$'
),
'PHP-suhosin.executor.include.whitelist': (
_("PHP - suhosin.executor.include.whitelist"),
r'.*$'
),
'PHP-upload_max_filesize': (
_("PHP - upload_max_filesize"),
r'^[0-9]{1,3}M$'
),
'PHP-zend_extension': (
_("PHP - zend_extension"),
r'^[^ ]+$'
),
# FCGID
'FcgidIdleTimeout': (
_("FCGI - Idle timeout"),
r'^[0-9]{1,3}$'
),
'FcgidBusyTimeout': (
_("FCGI - Busy timeout"),
r'^[0-9]{1,3}$'
),
'FcgidConnectTimeout': (
_("FCGI - Connection timeout"),
r'^[0-9]{1,3}$'
),
'FcgidIOTimeout': (
_("FCGI - IO timeout"),
r'^[0-9]{1,3}$'
),
'FcgidProcessLifeTime': (
_("FCGI - IO timeout"),
r'^[0-9]{1,4}$'
),
})
WEBAPPS_PHP_DISABLED_FUNCTIONS = getattr(settings, 'WEBAPPS_PHP_DISABLED_FUNCTION', [ WEBAPPS_PHP_DISABLED_FUNCTIONS = getattr(settings, 'WEBAPPS_PHP_DISABLED_FUNCTION', [
'exec', 'exec',
'passthru', 'passthru',
@ -246,3 +99,179 @@ WEBAPPS_PHP_DISABLED_FUNCTIONS = getattr(settings, 'WEBAPPS_PHP_DISABLED_FUNCTIO
'escapeshellarg', 'escapeshellarg',
'dl' 'dl'
]) ])
WEBAPPS_OPTIONS = getattr(settings, 'WEBAPPS_OPTIONS', {
# { name: ( verbose_name, [help_text], validation_regex ) }
# PHP
'enabled_functions': (
_("PHP - Enabled functions"),
' '.join(WEBAPPS_PHP_DISABLED_FUNCTIONS),
r'^[\w\.,-]+$'
),
'PHP-allow_url_include': (
_("PHP - Allow URL include"),
_("On or Off"),
r'^(On|Off|on|off)$'
),
'PHP-allow_url_fopen': (
_("PHP - allow_url_fopen"),
_("On or Off"),
r'^(On|Off|on|off)$'
),
'PHP-auto_append_file': (
_("PHP - Auto append file"),
r'^[\w\.,-/]+$'
),
'PHP-auto_prepend_file': (
_("PHP - Auto prepend file"),
r'^[\w\.,-/]+$'
),
'PHP-date.timezone': (
_("PHP - date.timezone"),
_("Timezone string 'Europe/London'."),
r'^\w+/\w+$'
),
'PHP-default_socket_timeout': (
_("PHP - Default socket timeout"),
_("Number between 0 and 999."),
r'^[0-9]{1,3}$'
),
'PHP-display_errors': (
_("PHP - Display errors"),
_("On or Off"),
r'^(On|Off|on|off)$'
),
'PHP-extension': (
_("PHP - Extension"),
r'^[^ ]+$'
),
'PHP-magic_quotes_gpc': (
_("PHP - Magic quotes GPC"),
_("On or Off"),
r'^(On|Off|on|off)$'
),
'PHP-magic_quotes_runtime': (
_("PHP - Magic quotes runtime"),
_("On or Off"),
r'^(On|Off|on|off)$'
),
'PHP-magic_quotes_sybase': (
_("PHP - Magic quotes sybase"),
_("On or Off"),
r'^(On|Off|on|off)$'
),
'PHP-max_execution_time': (
_("PHP - Max execution time"),
_("Number between 0 and 999."),
r'^[0-9]{1,3}$'
),
'PHP-max_input_time': (
_("PHP - Max input time"),
_("Number between 0 and 999."),
r'^[0-9]{1,3}$'
),
'PHP-memory_limit': (
_("PHP - Memory limit"),
_("Value between 0M and 999M."),
r'^[0-9]{1,3}M$'
),
'PHP-mysql.connect_timeout': (
_("PHP - Mysql connect timeout"),
_("Number between 0 and 999."),
r'^([0-9]){1,3}$'
),
'PHP-output_buffering': (
_("PHP - output_buffering"),
_("On or Off"),
r'^(On|Off|on|off)$'
),
'PHP-register_globals': (
_("PHP - Register globals"),
_("On or Off"),
r'^(On|Off|on|off)$'
),
'PHP-post_max_size': (
_("PHP - Post max size"),
_("Value between 0M and 999M."),
r'^[0-9]{1,3}M$'
),
'PHP-sendmail_path': (
_("PHP - sendmail_path"),
r'^[^ ]+$'
),
'PHP-session.bug_compat_warn': (
_("PHP - session.bug_compat_warn"),
_("On or Off"),
r'^(On|Off|on|off)$'
),
'PHP-session.auto_start': (
_("PHP - session.auto_start"),
_("On or Off"),
r'^(On|Off|on|off)$'
),
'PHP-safe_mode': (
_("PHP - Safe mode"),
_("On or Off"),
r'^(On|Off|on|off)$'
),
'PHP-suhosin.post.max_vars': (
_("PHP - Suhosin post max vars"),
_("Number between 0 and 9999."),
r'^[0-9]{1,4}$'
),
'PHP-suhosin.request.max_vars': (
_("PHP - Suhosin request max vars"),
_("Number between 0 and 9999."),
r'^[0-9]{1,4}$'
),
'PHP-suhosin.session.encrypt': (
_("PHP - suhosin.session.encrypt"),
_("On or Off"),
r'^(On|Off|on|off)$'
),
'PHP-suhosin.simulation': (
_("PHP - Suhosin simulation"),
_("On or Off"),
r'^(On|Off|on|off)$'
),
'PHP-suhosin.executor.include.whitelist': (
_("PHP - suhosin.executor.include.whitelist"),
r'.*$'
),
'PHP-upload_max_filesize': (
_("PHP - upload_max_filesize"),
_("Value between 0M and 999M."),
r'^[0-9]{1,3}M$'
),
'PHP-zend_extension': (
_("PHP - zend_extension"),
r'^[^ ]+$'
),
# FCGID
'FcgidIdleTimeout': (
_("FCGI - Idle timeout"),
_("Number between 0 and 999."),
r'^[0-9]{1,3}$'
),
'FcgidBusyTimeout': (
_("FCGI - Busy timeout"),
_("Number between 0 and 999."),
r'^[0-9]{1,3}$'
),
'FcgidConnectTimeout': (
_("FCGI - Connection timeout"),
_("Number of seconds between 0 and 999."),
r'^[0-9]{1,3}$'
),
'FcgidIOTimeout': (
_("FCGI - IO timeout"),
_("Number of seconds between 0 and 999."),
r'^[0-9]{1,3}$'
),
'FcgidProcessLifeTime': (
_("FCGI - IO timeout"),
_("Numbe of secondsr between 0 and 9999."),
r'^[0-9]{1,4}$'
),
})

View file

@ -6,6 +6,7 @@ from orchestra.admin import ExtendedModelAdmin
from orchestra.admin.utils import admin_link, change_url from orchestra.admin.utils import admin_link, change_url
from orchestra.apps.accounts.admin import AccountAdminMixin, SelectAccountAdminMixin from orchestra.apps.accounts.admin import AccountAdminMixin, SelectAccountAdminMixin
from . import settings
from .models import Content, Website, WebsiteOption from .models import Content, Website, WebsiteOption
@ -13,6 +14,11 @@ class WebsiteOptionInline(admin.TabularInline):
model = WebsiteOption model = WebsiteOption
extra = 1 extra = 1
OPTIONS_HELP_TEXT = str({
k: str(unicode(v[1])) if len(v) == 3 else ''
for k, v in settings.WEBSITES_OPTIONS.iteritems()
})
# class Media: # class Media:
# css = { # css = {
# 'all': ('orchestra/css/hide-inline-id.css',) # 'all': ('orchestra/css/hide-inline-id.css',)
@ -22,6 +28,19 @@ class WebsiteOptionInline(admin.TabularInline):
""" Make value input widget bigger """ """ Make value input widget bigger """
if db_field.name == 'value': if db_field.name == 'value':
kwargs['widget'] = forms.TextInput(attrs={'size':'100'}) kwargs['widget'] = forms.TextInput(attrs={'size':'100'})
if db_field.name == 'name':
options = {
}
kwargs['widget'] = forms.Select(attrs={
'onChange': """
siteoptions = %s;
valueelement = $("#"+this.id.replace("name", "value"));
valueelement.parent().find('p').remove();
valueelement.parent().append(
"<p class='help'>" + siteoptions[this.options[this.selectedIndex].value] + "</p>"
);
""" % self.OPTIONS_HELP_TEXT,
})
return super(WebsiteOptionInline, self).formfield_for_dbfield(db_field, **kwargs) return super(WebsiteOptionInline, self).formfield_for_dbfield(db_field, **kwargs)
@ -56,6 +75,7 @@ class WebsiteAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
) )
filter_by_account_fields = ['domains'] filter_by_account_fields = ['domains']
prefetch_related = ('domains', 'content_set__webapp') prefetch_related = ('domains', 'content_set__webapp')
search_fields = ('name', 'account__username', 'domains__name')
def display_domains(self, website): def display_domains(self, website):
domains = [] domains = []

View file

@ -168,6 +168,19 @@ class Apache2Backend(ServiceController):
self.append("if [[ ! $DISABLED ]]; then a2dissite %(site_unique_name)s.conf;\n" self.append("if [[ ! $DISABLED ]]; then a2dissite %(site_unique_name)s.conf;\n"
"else UPDATED=0; fi" % context) "else UPDATED=0; fi" % context)
def get_username(self, site):
option = site.options.filter('user_group')
if option:
return option[0].split()[0]
return site.account.username
def get_groupname(self, site):
option = site.options.filter('user_group')
if option and ' ' in option:
user, group = option.split()
return group
return site.account.username
def get_context(self, site): def get_context(self, site):
base_apache_conf = settings.WEBSITES_BASE_APACHE_CONF base_apache_conf = settings.WEBSITES_BASE_APACHE_CONF
sites_available = os.path.join(base_apache_conf, 'sites-available') sites_available = os.path.join(base_apache_conf, 'sites-available')
@ -177,8 +190,8 @@ class Apache2Backend(ServiceController):
'site_name': site.name, 'site_name': site.name,
'ip': settings.WEBSITES_DEFAULT_IP, 'ip': settings.WEBSITES_DEFAULT_IP,
'site_unique_name': site.unique_name, 'site_unique_name': site.unique_name,
'user': site.get_username(), 'user': self.get_username(site),
'group': site.get_groupname(), 'group': self.get_groupname(site),
'sites_enabled': sites_enabled, 'sites_enabled': sites_enabled,
'sites_available': "%s.conf" % os.path.join(sites_available, site.unique_name), 'sites_available': "%s.conf" % os.path.join(sites_available, site.unique_name),
'logs': site.get_www_log_path(), 'logs': site.get_www_log_path(),

View file

@ -50,12 +50,6 @@ class Website(models.Model):
if domain: if domain:
return '%s://%s' % (self.protocol, domain) return '%s://%s' % (self.protocol, domain)
def get_username(self):
return self.account.username
def get_groupname(self):
return self.get_username()
def get_www_log_path(self): def get_www_log_path(self):
context = { context = {
'unique_name': self.unique_name 'unique_name': self.unique_name
@ -80,7 +74,7 @@ class WebsiteOption(models.Model):
def clean(self): def clean(self):
""" validates name and value according to WEBSITES_WEBSITEOPTIONS """ """ validates name and value according to WEBSITES_WEBSITEOPTIONS """
__, regex = settings.WEBSITES_OPTIONS[self.name] regex = settings.WEBSITES_OPTIONS[self.name][-1]
if not re.match(regex, self.value): if not re.match(regex, self.value):
raise ValidationError({ raise ValidationError({
'value': ValidationError(_("'%(value)s' does not match %(regex)s."), 'value': ValidationError(_("'%(value)s' does not match %(regex)s."),

View file

@ -18,38 +18,47 @@ WEBSITES_DOMAIN_MODEL = getattr(settings, 'WEBSITES_DOMAIN_MODEL', 'domains.Doma
WEBSITES_OPTIONS = getattr(settings, 'WEBSITES_OPTIONS', { WEBSITES_OPTIONS = getattr(settings, 'WEBSITES_OPTIONS', {
# { name: ( verbose_name, validation_regex ) } # { name: ( verbose_name, [help_text], validation_regex ) }
'directory_protection': ( 'directory_protection': (
_("HTTPD - Directory protection"), _("HTTPD - Directory protection"),
r'^([\w/_]+)\s+(\".*\")\s+([\w/_\.]+)$' _("Space separated ..."),
r'^([\w/_]+)\s+(\".*\")\s+([\w/_\.]+)$',
), ),
'redirect': ( 'redirect': (
_("HTTPD - Redirection"), _("HTTPD - Redirection"),
r'^(permanent\s[^ ]+|[^ ]+)\s[^ ]+$' _("[permanent] &lt;website path&gt; &lt;destination URL&gt;"),
r'^(permanent\s[^ ]+|[^ ]+)\s[^ ]+$',
), ),
'ssl_ca': ( 'ssl_ca': (
_("HTTPD - SSL CA"), _("HTTPD - SSL CA"),
_("Filesystem path of the CA certificate file."),
r'^[^ ]+$' r'^[^ ]+$'
), ),
'ssl_cert': ( 'ssl_cert': (
_("HTTPD - SSL cert"), _("HTTPD - SSL cert"),
_("Filesystem path of the certificate file."),
r'^[^ ]+$' r'^[^ ]+$'
), ),
'ssl_key': ( 'ssl_key': (
_("HTTPD - SSL key"), _("HTTPD - SSL key"),
r'^[^ ]+$' _("Filesystem path of the key file."),
r'^[^ ]+$',
), ),
'sec_rule_remove': ( 'sec_rule_remove': (
_("HTTPD - SecRuleRemoveById"), _("HTTPD - SecRuleRemoveById"),
r'^[0-9\s]+$' _("Space separated ModSecurity rule IDs."),
r'^[0-9\s]+$',
), ),
'sec_engine': ( 'sec_engine': (
_("HTTPD - Disable Modsecurity"), _("HTTPD - Modsecurity engine"),
r'^[\w/_]+$' _("On or Off, defaults to On"),
r'^(On|Off)$',
), ),
'user_group': ( 'user_group': (
_("HTTPD - SuexecUserGroup"), _("HTTPD - SuexecUserGroup"),
r'^[\w/_]+\s[\w/_]+$' _("Username and optional groupname (user [group])"),
# TODO validate existing user/group
r'^[\w/_]+(\s[\w/_]+)*$',
), ),
}) })