Improved webapps and saas validation
This commit is contained in:
parent
dd84217320
commit
c55cff9a37
21
TODO.md
21
TODO.md
|
@ -195,23 +195,20 @@ Php binaries should have this format: /usr/bin/php5.2-cgi
|
||||||
* Orchestra global search box on the header, based https://github.com/django/django/blob/master/django/contrib/admin/options.py#L866 and iterating over all registered services and inspectin its admin.search_fields
|
* Orchestra global search box on the header, based https://github.com/django/django/blob/master/django/contrib/admin/options.py#L866 and iterating over all registered services and inspectin its admin.search_fields
|
||||||
|
|
||||||
|
|
||||||
* contain error on plugin missing key (plugin dissabled): NOP, fail hard is better than silently, perhaps fail at starttime? apploading
|
* contain error on plugin missing key (plugin dissabled): NOP, fail hard is better than silently, perhaps fail at starttime? apploading machinary
|
||||||
|
|
||||||
* contact.alternative_phone on a phone.tooltip, email:to
|
* contact.alternative_phone on a phone.tooltip, email:to
|
||||||
|
|
||||||
|
|
||||||
* better validate options and directives (url locations, filesystem paths, etc..)
|
* better validate options and directives (url locations, filesystem paths, etc..)
|
||||||
* filter php deprecated options out based on version
|
|
||||||
|
|
||||||
* make sure that you understand the risks
|
* make sure that you understand the risks
|
||||||
|
|
||||||
|
|
||||||
* full support for deactivation of services/accounts
|
* full support for deactivation of services/accounts
|
||||||
* Display admin.is_active (disabled account/order by)
|
* Display admin.is_active (disabled account special icon and order by support)
|
||||||
|
|
||||||
|
|
||||||
* lock resource monitoring
|
* lock resource monitoring
|
||||||
|
|
||||||
* -EXecCGI in common CMS upload locations /wp-upload/upload/uploads
|
* -EXecCGI in common CMS upload locations /wp-upload/upload/uploads
|
||||||
* cgi user / pervent shell access
|
* cgi user / pervent shell access
|
||||||
|
|
||||||
|
@ -219,14 +216,6 @@ Php binaries should have this format: /usr/bin/php5.2-cgi
|
||||||
|
|
||||||
* disable anonymized list options (mailman)
|
* disable anonymized list options (mailman)
|
||||||
|
|
||||||
* webapps directory protection and disable excecgi
|
|
||||||
|
|
||||||
* php-fpm disable execCGI
|
|
||||||
|
|
||||||
* SuexecUserGroup needs to be per app othewise wrapper/fpm user can't be correct
|
|
||||||
|
|
||||||
* wprdess-mu saas app that create a Website object????
|
|
||||||
|
|
||||||
* tags = GenericRelation(TaggedItem, related_query_name='bookmarks')
|
* tags = GenericRelation(TaggedItem, related_query_name='bookmarks')
|
||||||
|
|
||||||
* make home for all systemusers (/home/username) and fix monitors
|
* make home for all systemusers (/home/username) and fix monitors
|
||||||
|
@ -243,15 +232,11 @@ require_once(‘/etc/moodles/’.$moodle_host.‘config.php’);``` moodle/drupl
|
||||||
|
|
||||||
* normurlpath '' return '/'
|
* normurlpath '' return '/'
|
||||||
|
|
||||||
* rename webapps.type to something more generic
|
|
||||||
|
|
||||||
* initial configuration of multisite sas apps with password stored in DATA
|
* initial configuration of multisite sas apps with password stored in DATA
|
||||||
|
|
||||||
* webapps installation complete, passowrd protected
|
* webapps installation complete, passowrd protected
|
||||||
* saas.initial_password autogenerated (ok because its random and not user provided) vs saas.password /change_Form provided + send email with initial_password
|
* saas.initial_password autogenerated (ok because its random and not user provided) vs saas.password /change_Form provided + send email with initial_password
|
||||||
|
|
||||||
* disable saas apps
|
|
||||||
|
|
||||||
* more robust backend error handling, continue executing but exit code > 0 if failure, replace exit_code=0; do_sometging || exit_code=1
|
* more robust backend error handling, continue executing but exit code > 0 if failure, replace exit_code=0; do_sometging || exit_code=1
|
||||||
|
|
||||||
* saas require unique emails? connect to backend server to find out because they change
|
* saas require unique emails? connect to backend server to find out because they change
|
||||||
|
@ -260,6 +245,4 @@ require_once(‘/etc/moodles/’.$moodle_host.‘config.php’);``` moodle/drupl
|
||||||
|
|
||||||
* website directives uniquenes validation on serializers
|
* website directives uniquenes validation on serializers
|
||||||
|
|
||||||
* gitlab store id, username changes
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,8 @@ from .services import SoftwareService
|
||||||
|
|
||||||
|
|
||||||
class SaaSAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin):
|
class SaaSAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin):
|
||||||
list_display = ('name', 'service', 'display_site_domain', 'account_link')
|
list_display = ('name', 'service', 'display_site_domain', 'account_link', 'is_active')
|
||||||
list_filter = ('service',)
|
list_filter = ('service', 'is_active')
|
||||||
change_readonly_fields = ('service',)
|
change_readonly_fields = ('service',)
|
||||||
plugin = SoftwareService
|
plugin = SoftwareService
|
||||||
plugin_field = 'service'
|
plugin_field = 'service'
|
||||||
|
|
|
@ -22,9 +22,10 @@ class GitLabSaaSBackend(ServiceController):
|
||||||
user_id = saas.data['user_id']
|
user_id = saas.data['user_id']
|
||||||
return self.get_base_url() + '/users/%i' % user_id
|
return self.get_base_url() + '/users/%i' % user_id
|
||||||
|
|
||||||
def validate_response(self, response, status_codes):
|
def validate_response(self, response, *status_codes):
|
||||||
if response.status_code not in status_codes:
|
if response.status_code not in status_codes:
|
||||||
raise RuntimeError("[%i] %s" % (response.status_code, response.content))
|
raise RuntimeError("[%i] %s" % (response.status_code, response.content))
|
||||||
|
return json.loads(response.content)
|
||||||
|
|
||||||
def authenticate(self):
|
def authenticate(self):
|
||||||
login_url = self.get_base_url() + '/session'
|
login_url = self.get_base_url() + '/session'
|
||||||
|
@ -33,8 +34,8 @@ class GitLabSaaSBackend(ServiceController):
|
||||||
'password': settings.SAAS_GITLAB_ROOT_PASSWORD,
|
'password': settings.SAAS_GITLAB_ROOT_PASSWORD,
|
||||||
}
|
}
|
||||||
response = requests.post(login_url, data=data)
|
response = requests.post(login_url, data=data)
|
||||||
self.validate_response(response, [201])
|
session = self.validate_response(response, 201)
|
||||||
token = json.loads(response.content)['private_token']
|
token = session['private_token']
|
||||||
self.headers = {
|
self.headers = {
|
||||||
'PRIVATE-TOKEN': token,
|
'PRIVATE-TOKEN': token,
|
||||||
}
|
}
|
||||||
|
@ -49,9 +50,7 @@ class GitLabSaaSBackend(ServiceController):
|
||||||
'name': saas.account.get_full_name(),
|
'name': saas.account.get_full_name(),
|
||||||
}
|
}
|
||||||
response = requests.post(user_url, data=data, headers=self.headers)
|
response = requests.post(user_url, data=data, headers=self.headers)
|
||||||
self.validate_response(response, [201])
|
user = self.validate_response(response, 201)
|
||||||
print response.content
|
|
||||||
user = json.loads(response.content)
|
|
||||||
saas.data['user_id'] = user['id']
|
saas.data['user_id'] = user['id']
|
||||||
# Using queryset update to avoid triggering backends with the post_save signal
|
# Using queryset update to avoid triggering backends with the post_save signal
|
||||||
type(saas).objects.filter(pk=saas.pk).update(data=saas.data)
|
type(saas).objects.filter(pk=saas.pk).update(data=saas.data)
|
||||||
|
@ -60,19 +59,32 @@ class GitLabSaaSBackend(ServiceController):
|
||||||
def change_password(self, saas, server):
|
def change_password(self, saas, server):
|
||||||
self.authenticate()
|
self.authenticate()
|
||||||
user_url = self.get_user_url(saas)
|
user_url = self.get_user_url(saas)
|
||||||
data = {
|
response = requests.get(user_url, headers=self.headers)
|
||||||
'password': saas.password,
|
user = self.validate_response(response, 200)
|
||||||
}
|
user = json.loads(response.content)
|
||||||
response = requests.patch(user_url, data=data, headers=self.headers)
|
user['password'] = saas.password
|
||||||
self.validate_response(response, [200])
|
response = requests.put(user_url, data=user, headers=self.headers)
|
||||||
print json.dumps(json.loads(response.content), indent=4)
|
user = self.validate_response(response, 200)
|
||||||
|
print json.dumps(user, indent=4)
|
||||||
|
|
||||||
|
def set_state(self, saas, server):
|
||||||
|
# TODO http://feedback.gitlab.com/forums/176466-general/suggestions/4098632-add-administrative-api-call-to-block-users
|
||||||
|
return
|
||||||
|
self.authenticate()
|
||||||
|
user_url = self.get_user_url(saas)
|
||||||
|
response = requests.get(user_url, headers=self.headers)
|
||||||
|
user = self.validate_response(response, 200)
|
||||||
|
user['state'] = 'active' if saas.active else 'blocked',
|
||||||
|
response = requests.patch(user_url, data=user, headers=self.headers)
|
||||||
|
user = self.validate_response(response, 200)
|
||||||
|
print json.dumps(user, indent=4)
|
||||||
|
|
||||||
def delete_user(self, saas, server):
|
def delete_user(self, saas, server):
|
||||||
self.authenticate()
|
self.authenticate()
|
||||||
user_url = self.get_user_url(saas)
|
user_url = self.get_user_url(saas)
|
||||||
response = requests.delete(user_url, headers=self.headers)
|
response = requests.delete(user_url, headers=self.headers)
|
||||||
self.validate_response(response, [200, 404])
|
user = self.validate_response(response, 200, 404)
|
||||||
print json.dumps(json.loads(response.content), indent=4)
|
print json.dumps(user, indent=4)
|
||||||
|
|
||||||
def _validate_creation(self, saas, server):
|
def _validate_creation(self, saas, server):
|
||||||
""" checks if a saas object is valid for creation on the server side """
|
""" checks if a saas object is valid for creation on the server side """
|
||||||
|
@ -96,6 +108,7 @@ class GitLabSaaSBackend(ServiceController):
|
||||||
self.append(self.change_password, saas)
|
self.append(self.change_password, saas)
|
||||||
else:
|
else:
|
||||||
self.append(self.create_user, saas)
|
self.append(self.create_user, saas)
|
||||||
|
self.append(self.set_state, saas)
|
||||||
|
|
||||||
def delete(self, saas):
|
def delete(self, saas):
|
||||||
self.append(self.delete_user, saas)
|
self.append(self.delete_user, saas)
|
||||||
|
|
|
@ -19,6 +19,8 @@ class SaaS(models.Model):
|
||||||
validators=[validators.validate_username])
|
validators=[validators.validate_username])
|
||||||
account = models.ForeignKey('accounts.Account', verbose_name=_("account"),
|
account = models.ForeignKey('accounts.Account', verbose_name=_("account"),
|
||||||
related_name='saas')
|
related_name='saas')
|
||||||
|
is_active = models.BooleanField(_("active"), default=True,
|
||||||
|
help_text=_("Designates whether this service should be treated as active. "))
|
||||||
data = JSONField(_("data"), default={},
|
data = JSONField(_("data"), default={},
|
||||||
help_text=_("Extra information dependent of each service."))
|
help_text=_("Extra information dependent of each service."))
|
||||||
|
|
||||||
|
@ -41,6 +43,10 @@ class SaaS(models.Model):
|
||||||
""" Per request lived service_instance """
|
""" Per request lived service_instance """
|
||||||
return self.service_class(self)
|
return self.service_class(self)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def active(self):
|
||||||
|
return self.is_active and self.account.is_active
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
self.data = self.service_instance.clean_data()
|
self.data = self.service_instance.clean_data()
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,20 @@ class AppOption(Plugin):
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
class PHPAppOption(AppOption):
|
||||||
|
deprecated = None
|
||||||
|
group = AppOption.PHP
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
super(PHPAppOption, self).validate()
|
||||||
|
if self.deprecated:
|
||||||
|
php_version = self.instance.webapp.type_instance.get_php_version()
|
||||||
|
if php_version and php_version > self.deprecated:
|
||||||
|
raise ValidationError(
|
||||||
|
_("This option is deprecated since PHP version %s.") % str(self.deprecated)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class PublicRoot(AppOption):
|
class PublicRoot(AppOption):
|
||||||
name = 'public-root'
|
name = 'public-root'
|
||||||
verbose_name = _("Public root")
|
verbose_name = _("Public root")
|
||||||
|
@ -77,193 +91,171 @@ class Processes(AppOption):
|
||||||
group = AppOption.PROCESS
|
group = AppOption.PROCESS
|
||||||
|
|
||||||
|
|
||||||
class PHPEnabledFunctions(AppOption):
|
class PHPEnabledFunctions(PHPAppOption):
|
||||||
name = 'enabled_functions'
|
name = 'enabled_functions'
|
||||||
verbose_name = _("Enabled functions")
|
verbose_name = _("Enabled functions")
|
||||||
help_text = ' '.join(settings.WEBAPPS_PHP_DISABLED_FUNCTIONS)
|
help_text = ' '.join(settings.WEBAPPS_PHP_DISABLED_FUNCTIONS)
|
||||||
regex = r'^[\w\.,-]+$'
|
regex = r'^[\w\.,-]+$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPAllowURLInclude(AppOption):
|
class PHPAllowURLInclude(PHPAppOption):
|
||||||
name = 'allow_url_include'
|
name = 'allow_url_include'
|
||||||
verbose_name = _("Allow URL include")
|
verbose_name = _("Allow URL include")
|
||||||
help_text = _("Allows the use of URL-aware fopen wrappers with include, include_once, require, "
|
help_text = _("Allows the use of URL-aware fopen wrappers with include, include_once, require, "
|
||||||
"require_once (On or Off).")
|
"require_once (On or Off).")
|
||||||
regex = r'^(On|Off|on|off)$'
|
regex = r'^(On|Off|on|off)$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPAllowURLFopen(AppOption):
|
class PHPAllowURLFopen(PHPAppOption):
|
||||||
name = 'allow_url_fopen'
|
name = 'allow_url_fopen'
|
||||||
verbose_name = _("Allow URL fopen")
|
verbose_name = _("Allow URL fopen")
|
||||||
help_text = _("Enables the URL-aware fopen wrappers that enable accessing URL object like files (On or Off).")
|
help_text = _("Enables the URL-aware fopen wrappers that enable accessing URL object like files (On or Off).")
|
||||||
regex = r'^(On|Off|on|off)$'
|
regex = r'^(On|Off|on|off)$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPAutoAppendFile(AppOption):
|
class PHPAutoAppendFile(PHPAppOption):
|
||||||
name = 'auto_append_file'
|
name = 'auto_append_file'
|
||||||
verbose_name = _("Auto append file")
|
verbose_name = _("Auto append file")
|
||||||
help_text = _("Specifies the name of a file that is automatically parsed after the main file.")
|
help_text = _("Specifies the name of a file that is automatically parsed after the main file.")
|
||||||
regex = r'^[\w\.,-/]+$'
|
regex = r'^[\w\.,-/]+$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPAutoPrependFile(AppOption):
|
class PHPAutoPrependFile(PHPAppOption):
|
||||||
name = 'auto_prepend_file'
|
name = 'auto_prepend_file'
|
||||||
verbose_name = _("Auto prepend file")
|
verbose_name = _("Auto prepend file")
|
||||||
help_text = _("Specifies the name of a file that is automatically parsed before the main file.")
|
help_text = _("Specifies the name of a file that is automatically parsed before the main file.")
|
||||||
regex = r'^[\w\.,-/]+$'
|
regex = r'^[\w\.,-/]+$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPDateTimeZone(AppOption):
|
class PHPDateTimeZone(PHPAppOption):
|
||||||
name = 'date.timezone'
|
name = 'date.timezone'
|
||||||
verbose_name = _("date.timezone")
|
verbose_name = _("date.timezone")
|
||||||
help_text = _("Sets the default timezone used by all date/time functions (Timezone string 'Europe/London').")
|
help_text = _("Sets the default timezone used by all date/time functions (Timezone string 'Europe/London').")
|
||||||
regex = r'^\w+/\w+$'
|
regex = r'^\w+/\w+$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPDefaultSocketTimeout(AppOption):
|
class PHPDefaultSocketTimeout(PHPAppOption):
|
||||||
name = 'default_socket_timeout'
|
name = 'default_socket_timeout'
|
||||||
verbose_name = _("Default socket timeout")
|
verbose_name = _("Default socket timeout")
|
||||||
help_text = _("Number between 0 and 999.")
|
help_text = _("Number between 0 and 999.")
|
||||||
regex = r'^[0-9]{1,3}$'
|
regex = r'^[0-9]{1,3}$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPDisplayErrors(AppOption):
|
class PHPDisplayErrors(PHPAppOption):
|
||||||
name = 'display_errors'
|
name = 'display_errors'
|
||||||
verbose_name = _("Display errors")
|
verbose_name = _("Display errors")
|
||||||
help_text = _("Determines whether errors should be printed to the screen as part of the output or "
|
help_text = _("Determines whether errors should be printed to the screen as part of the output or "
|
||||||
"if they should be hidden from the user (On or Off).")
|
"if they should be hidden from the user (On or Off).")
|
||||||
regex = r'^(On|Off|on|off)$'
|
regex = r'^(On|Off|on|off)$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPExtension(AppOption):
|
class PHPExtension(PHPAppOption):
|
||||||
name = 'extension'
|
name = 'extension'
|
||||||
verbose_name = _("Extension")
|
verbose_name = _("Extension")
|
||||||
regex = r'^[^ ]+$'
|
regex = r'^[^ ]+$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPMagicQuotesGPC(AppOption):
|
class PHPMagicQuotesGPC(PHPAppOption):
|
||||||
name = 'magic_quotes_gpc'
|
name = 'magic_quotes_gpc'
|
||||||
verbose_name = _("Magic quotes GPC")
|
verbose_name = _("Magic quotes GPC")
|
||||||
help_text = _("Sets the magic_quotes state for GPC (Get/Post/Cookie) operations (On or Off) "
|
help_text = _("Sets the magic_quotes state for GPC (Get/Post/Cookie) operations (On or Off) "
|
||||||
"<b>DEPRECATED as of PHP 5.3.0</b>.")
|
"<b>DEPRECATED as of PHP 5.3.0</b>.")
|
||||||
regex = r'^(On|Off|on|off)$'
|
regex = r'^(On|Off|on|off)$'
|
||||||
deprecated=5.3
|
deprecated = 5.3
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPMagicQuotesRuntime(AppOption):
|
class PHPMagicQuotesRuntime(PHPAppOption):
|
||||||
name = 'magic_quotes_runtime'
|
name = 'magic_quotes_runtime'
|
||||||
verbose_name = _("Magic quotes runtime")
|
verbose_name = _("Magic quotes runtime")
|
||||||
help_text = _("Functions that return data from any sort of external source will have quotes escaped "
|
help_text = _("Functions that return data from any sort of external source will have quotes escaped "
|
||||||
"with a backslash (On or Off) <b>DEPRECATED as of PHP 5.3.0</b>.")
|
"with a backslash (On or Off) <b>DEPRECATED as of PHP 5.3.0</b>.")
|
||||||
regex = r'^(On|Off|on|off)$'
|
regex = r'^(On|Off|on|off)$'
|
||||||
deprecated=5.3
|
deprecated = 5.3
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPMaginQuotesSybase(AppOption):
|
class PHPMaginQuotesSybase(PHPAppOption):
|
||||||
name = 'magic_quotes_sybase'
|
name = 'magic_quotes_sybase'
|
||||||
verbose_name = _("Magic quotes sybase")
|
verbose_name = _("Magic quotes sybase")
|
||||||
help_text = _("Single-quote is escaped with a single-quote instead of a backslash (On or Off).")
|
help_text = _("Single-quote is escaped with a single-quote instead of a backslash (On or Off).")
|
||||||
regex = r'^(On|Off|on|off)$'
|
regex = r'^(On|Off|on|off)$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPMaxExecutonTime(AppOption):
|
class PHPMaxExecutonTime(PHPAppOption):
|
||||||
name = 'max_execution_time'
|
name = 'max_execution_time'
|
||||||
verbose_name = _("Max execution time")
|
verbose_name = _("Max execution time")
|
||||||
help_text = _("Maximum time in seconds a script is allowed to run before it is terminated by "
|
help_text = _("Maximum time in seconds a script is allowed to run before it is terminated by "
|
||||||
"the parser (Integer between 0 and 999).")
|
"the parser (Integer between 0 and 999).")
|
||||||
regex = r'^[0-9]{1,3}$'
|
regex = r'^[0-9]{1,3}$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPMaxInputTime(AppOption):
|
class PHPMaxInputTime(PHPAppOption):
|
||||||
name = 'max_input_time'
|
name = 'max_input_time'
|
||||||
verbose_name = _("Max input time")
|
verbose_name = _("Max input time")
|
||||||
help_text = _("Maximum time in seconds a script is allowed to parse input data, like POST and GET "
|
help_text = _("Maximum time in seconds a script is allowed to parse input data, like POST and GET "
|
||||||
"(Integer between 0 and 999).")
|
"(Integer between 0 and 999).")
|
||||||
regex = r'^[0-9]{1,3}$'
|
regex = r'^[0-9]{1,3}$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPMaxInputVars(AppOption):
|
class PHPMaxInputVars(PHPAppOption):
|
||||||
name = 'max_input_vars'
|
name = 'max_input_vars'
|
||||||
verbose_name = _("Max input vars")
|
verbose_name = _("Max input vars")
|
||||||
help_text = _("How many input variables may be accepted (limit is applied to $_GET, $_POST "
|
help_text = _("How many input variables may be accepted (limit is applied to $_GET, $_POST "
|
||||||
"and $_COOKIE superglobal separately) (Integer between 0 and 9999).")
|
"and $_COOKIE superglobal separately) (Integer between 0 and 9999).")
|
||||||
regex = r'^[0-9]{1,4}$'
|
regex = r'^[0-9]{1,4}$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPMemoryLimit(AppOption):
|
class PHPMemoryLimit(PHPAppOption):
|
||||||
name = 'memory_limit'
|
name = 'memory_limit'
|
||||||
verbose_name = _("Memory limit")
|
verbose_name = _("Memory limit")
|
||||||
help_text = _("This sets the maximum amount of memory in bytes that a script is allowed to allocate "
|
help_text = _("This sets the maximum amount of memory in bytes that a script is allowed to allocate "
|
||||||
"(Value between 0M and 999M).")
|
"(Value between 0M and 999M).")
|
||||||
regex = r'^[0-9]{1,3}M$'
|
regex = r'^[0-9]{1,3}M$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPMySQLConnectTimeout(AppOption):
|
class PHPMySQLConnectTimeout(PHPAppOption):
|
||||||
name = 'mysql.connect_timeout'
|
name = 'mysql.connect_timeout'
|
||||||
verbose_name = _("Mysql connect timeout")
|
verbose_name = _("Mysql connect timeout")
|
||||||
help_text = _("Number between 0 and 999.")
|
help_text = _("Number between 0 and 999.")
|
||||||
regex = r'^([0-9]){1,3}$'
|
regex = r'^([0-9]){1,3}$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPOutputBuffering(AppOption):
|
class PHPOutputBuffering(PHPAppOption):
|
||||||
name = 'output_buffering'
|
name = 'output_buffering'
|
||||||
verbose_name = _("Output buffering")
|
verbose_name = _("Output buffering")
|
||||||
help_text = _("Turn on output buffering (On or Off).")
|
help_text = _("Turn on output buffering (On or Off).")
|
||||||
regex = r'^(On|Off|on|off)$'
|
regex = r'^(On|Off|on|off)$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPRegisterGlobals(AppOption):
|
class PHPRegisterGlobals(PHPAppOption):
|
||||||
name = 'register_globals'
|
name = 'register_globals'
|
||||||
verbose_name = _("Register globals")
|
verbose_name = _("Register globals")
|
||||||
help_text = _("Whether or not to register the EGPCS (Environment, GET, POST, Cookie, Server) "
|
help_text = _("Whether or not to register the EGPCS (Environment, GET, POST, Cookie, Server) "
|
||||||
"variables as global variables (On or Off).")
|
"variables as global variables (On or Off).")
|
||||||
regex = r'^(On|Off|on|off)$'
|
regex = r'^(On|Off|on|off)$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPPostMaxSize(AppOption):
|
class PHPPostMaxSize(PHPAppOption):
|
||||||
name = 'post_max_size'
|
name = 'post_max_size'
|
||||||
verbose_name = _("Post max size")
|
verbose_name = _("Post max size")
|
||||||
help_text = _("Sets max size of post data allowed (Value between 0M and 999M).")
|
help_text = _("Sets max size of post data allowed (Value between 0M and 999M).")
|
||||||
regex = r'^[0-9]{1,3}M$'
|
regex = r'^[0-9]{1,3}M$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPSendmailPath(AppOption):
|
class PHPSendmailPath(PHPAppOption):
|
||||||
name = 'sendmail_path'
|
name = 'sendmail_path'
|
||||||
verbose_name = _("sendmail_path")
|
verbose_name = _("sendmail_path")
|
||||||
help_text = _("Where the sendmail program can be found.")
|
help_text = _("Where the sendmail program can be found.")
|
||||||
regex = r'^[^ ]+$'
|
regex = r'^[^ ]+$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPSessionBugCompatWarn(AppOption):
|
class PHPSessionBugCompatWarn(PHPAppOption):
|
||||||
name = 'session.bug_compat_warn'
|
name = 'session.bug_compat_warn'
|
||||||
verbose_name = _("session.bug_compat_warn")
|
verbose_name = _("session.bug_compat_warn")
|
||||||
help_text = _("Enables an PHP bug on session initialization for legacy behaviour (On or Off).")
|
help_text = _("Enables an PHP bug on session initialization for legacy behaviour (On or Off).")
|
||||||
regex = r'^(On|Off|on|off)$'
|
regex = r'^(On|Off|on|off)$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPSessionAutoStart(AppOption):
|
class PHPSessionAutoStart(PHPAppOption):
|
||||||
name = 'session.auto_start'
|
name = 'session.auto_start'
|
||||||
verbose_name = _("session.auto_start")
|
verbose_name = _("session.auto_start")
|
||||||
help_text = _("Specifies whether the session module starts a session automatically on request "
|
help_text = _("Specifies whether the session module starts a session automatically on request "
|
||||||
|
@ -272,72 +264,63 @@ class PHPSessionAutoStart(AppOption):
|
||||||
group = AppOption.PHP
|
group = AppOption.PHP
|
||||||
|
|
||||||
|
|
||||||
class PHPSafeMode(AppOption):
|
class PHPSafeMode(PHPAppOption):
|
||||||
name = 'safe_mode'
|
name = 'safe_mode'
|
||||||
verbose_name = _("Safe mode")
|
verbose_name = _("Safe mode")
|
||||||
help_text = _("Whether to enable PHP's safe mode (On or Off) <b>DEPRECATED as of PHP 5.3.0</b>")
|
help_text = _("Whether to enable PHP's safe mode (On or Off) <b>DEPRECATED as of PHP 5.3.0</b>")
|
||||||
regex = r'^(On|Off|on|off)$'
|
regex = r'^(On|Off|on|off)$'
|
||||||
deprecated=5.3
|
deprecated=5.3
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPSuhosinPostMaxVars(AppOption):
|
class PHPSuhosinPostMaxVars(PHPAppOption):
|
||||||
name = 'suhosin.post.max_vars'
|
name = 'suhosin.post.max_vars'
|
||||||
verbose_name = _("Suhosin POST max vars")
|
verbose_name = _("Suhosin POST max vars")
|
||||||
help_text = _("Number between 0 and 9999.")
|
help_text = _("Number between 0 and 9999.")
|
||||||
regex = r'^[0-9]{1,4}$'
|
regex = r'^[0-9]{1,4}$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPSuhosinGetMaxVars(AppOption):
|
class PHPSuhosinGetMaxVars(PHPAppOption):
|
||||||
name = 'suhosin.get.max_vars'
|
name = 'suhosin.get.max_vars'
|
||||||
verbose_name = _("Suhosin GET max vars")
|
verbose_name = _("Suhosin GET max vars")
|
||||||
help_text = _("Number between 0 and 9999.")
|
help_text = _("Number between 0 and 9999.")
|
||||||
regex = r'^[0-9]{1,4}$'
|
regex = r'^[0-9]{1,4}$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPSuhosinRequestMaxVars(AppOption):
|
class PHPSuhosinRequestMaxVars(PHPAppOption):
|
||||||
name = 'suhosin.request.max_vars'
|
name = 'suhosin.request.max_vars'
|
||||||
verbose_name = _("Suhosin request max vars")
|
verbose_name = _("Suhosin request max vars")
|
||||||
help_text = _("Number between 0 and 9999.")
|
help_text = _("Number between 0 and 9999.")
|
||||||
regex = r'^[0-9]{1,4}$'
|
regex = r'^[0-9]{1,4}$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPSuhosinSessionEncrypt(AppOption):
|
class PHPSuhosinSessionEncrypt(PHPAppOption):
|
||||||
name = 'suhosin.session.encrypt'
|
name = 'suhosin.session.encrypt'
|
||||||
verbose_name = _("suhosin.session.encrypt")
|
verbose_name = _("suhosin.session.encrypt")
|
||||||
help_text = _("On or Off")
|
help_text = _("On or Off")
|
||||||
regex = r'^(On|Off|on|off)$'
|
regex = r'^(On|Off|on|off)$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPSuhosinSimulation(AppOption):
|
class PHPSuhosinSimulation(PHPAppOption):
|
||||||
name = 'suhosin.simulation'
|
name = 'suhosin.simulation'
|
||||||
verbose_name = _("Suhosin simulation")
|
verbose_name = _("Suhosin simulation")
|
||||||
help_text = _("On or Off")
|
help_text = _("On or Off")
|
||||||
regex = r'^(On|Off|on|off)$'
|
regex = r'^(On|Off|on|off)$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPSuhosinExecutorIncludeWhitelist(AppOption):
|
class PHPSuhosinExecutorIncludeWhitelist(PHPAppOption):
|
||||||
name = 'suhosin.executor.include.whitelist'
|
name = 'suhosin.executor.include.whitelist'
|
||||||
verbose_name = _("suhosin.executor.include.whitelist")
|
verbose_name = _("suhosin.executor.include.whitelist")
|
||||||
regex = r'.*$'
|
regex = r'.*$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPUploadMaxFileSize(AppOption):
|
class PHPUploadMaxFileSize(PHPAppOption):
|
||||||
name = 'upload_max_filesize'
|
name = 'upload_max_filesize'
|
||||||
verbose_name = _("upload_max_filesize")
|
verbose_name = _("upload_max_filesize")
|
||||||
help_text = _("Value between 0M and 999M.")
|
help_text = _("Value between 0M and 999M.")
|
||||||
regex = r'^[0-9]{1,3}M$'
|
regex = r'^[0-9]{1,3}M$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
||||||
|
|
||||||
class PHPZendExtension(AppOption):
|
class PHPZendExtension(PHPAppOption):
|
||||||
name = 'zend_extension'
|
name = 'zend_extension'
|
||||||
verbose_name = _("Zend extension")
|
verbose_name = _("Zend extension")
|
||||||
regex = r'^[^ ]+$'
|
regex = r'^[^ ]+$'
|
||||||
group = AppOption.PHP
|
|
||||||
|
|
|
@ -36,14 +36,6 @@ class AppType(plugins.Plugin):
|
||||||
'name': _("A WordPress blog with this name already exists."),
|
'name': _("A WordPress blog with this name already exists."),
|
||||||
})
|
})
|
||||||
|
|
||||||
@classmethod
|
|
||||||
@cached
|
|
||||||
def get_php_options(cls):
|
|
||||||
# TODO validate php options once a php version has been selected (deprecated directives)
|
|
||||||
php_version = getattr(cls, 'php_version', 1)
|
|
||||||
php_options = AppOption.get_option_groups()[AppOption.PHP]
|
|
||||||
return [op for op in php_options if getattr(cls, 'deprecated', 99) > php_version]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@cached
|
@cached
|
||||||
def get_options(cls):
|
def get_options(cls):
|
||||||
|
@ -52,8 +44,6 @@ class AppType(plugins.Plugin):
|
||||||
options = []
|
options = []
|
||||||
for group in cls.option_groups:
|
for group in cls.option_groups:
|
||||||
group_options = groups[group]
|
group_options = groups[group]
|
||||||
if group == AppOption.PHP:
|
|
||||||
group_options = cls.get_php_options()
|
|
||||||
if group is None:
|
if group is None:
|
||||||
options.insert(0, (group, group_options))
|
options.insert(0, (group, group_options))
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -7,8 +7,10 @@ from rest_framework import serializers
|
||||||
|
|
||||||
from orchestra.forms import widgets
|
from orchestra.forms import widgets
|
||||||
from orchestra.plugins.forms import PluginDataForm
|
from orchestra.plugins.forms import PluginDataForm
|
||||||
|
from orchestra.utils.functional import cached
|
||||||
|
|
||||||
from .. import settings
|
from .. import settings
|
||||||
|
from ..options import AppOption
|
||||||
|
|
||||||
from . import AppType
|
from . import AppType
|
||||||
|
|
||||||
|
@ -57,6 +59,12 @@ class PHPApp(AppType):
|
||||||
def get_detail(self):
|
def get_detail(self):
|
||||||
return self.instance.data.get('php_version', '')
|
return self.instance.data.get('php_version', '')
|
||||||
|
|
||||||
|
@cached
|
||||||
|
def get_php_options(self):
|
||||||
|
php_version = self.get_php_version()
|
||||||
|
php_options = AppOption.get_option_groups()[AppOption.PHP]
|
||||||
|
return [op for op in php_options if getattr(self, 'deprecated', 999) > php_version]
|
||||||
|
|
||||||
def get_php_init_vars(self, merge=False):
|
def get_php_init_vars(self, merge=False):
|
||||||
"""
|
"""
|
||||||
process php options for inclusion on php.ini
|
process php options for inclusion on php.ini
|
||||||
|
@ -72,7 +80,7 @@ class PHPApp(AppType):
|
||||||
for webapp in webapps:
|
for webapp in webapps:
|
||||||
if webapp.type_instance.get_php_version == php_version:
|
if webapp.type_instance.get_php_version == php_version:
|
||||||
options += list(webapp.options.all())
|
options += list(webapp.options.all())
|
||||||
php_options = [option.name for option in type(self).get_php_options()]
|
php_options = [option.name for option in self.get_php_options()]
|
||||||
enabled_functions = set()
|
enabled_functions = set()
|
||||||
for opt in options:
|
for opt in options:
|
||||||
if opt.name in php_options:
|
if opt.name in php_options:
|
||||||
|
|
|
@ -10,7 +10,6 @@ from orchestra.utils.python import import_class
|
||||||
from . import settings
|
from . import settings
|
||||||
|
|
||||||
|
|
||||||
# TODO multiple and unique validation support in the formset
|
|
||||||
class SiteDirective(Plugin):
|
class SiteDirective(Plugin):
|
||||||
HTTPD = 'HTTPD'
|
HTTPD = 'HTTPD'
|
||||||
SEC = 'ModSecurity'
|
SEC = 'ModSecurity'
|
||||||
|
@ -141,7 +140,6 @@ class WordPressSaaS(SiteDirective):
|
||||||
name = 'wordpress-saas'
|
name = 'wordpress-saas'
|
||||||
verbose_name = "WordPress SaaS"
|
verbose_name = "WordPress SaaS"
|
||||||
help_text = _("URL path for mounting wordpress multisite.")
|
help_text = _("URL path for mounting wordpress multisite.")
|
||||||
# fpm_listen = settings.WEBAPPS_WORDPRESSMU_LISTEN
|
|
||||||
group = SiteDirective.SAAS
|
group = SiteDirective.SAAS
|
||||||
regex = r'^/[^ ]*$'
|
regex = r'^/[^ ]*$'
|
||||||
unique_value = True
|
unique_value = True
|
||||||
|
@ -151,7 +149,6 @@ class DokuWikiSaaS(SiteDirective):
|
||||||
name = 'dokuwiki-saas'
|
name = 'dokuwiki-saas'
|
||||||
verbose_name = "DokuWiki SaaS"
|
verbose_name = "DokuWiki SaaS"
|
||||||
help_text = _("URL path for mounting wordpress multisite.")
|
help_text = _("URL path for mounting wordpress multisite.")
|
||||||
# fpm_listen = settings.WEBAPPS_DOKUWIKIMU_LISTEN
|
|
||||||
group = SiteDirective.SAAS
|
group = SiteDirective.SAAS
|
||||||
regex = r'^/[^ ]*$'
|
regex = r'^/[^ ]*$'
|
||||||
unique_value = True
|
unique_value = True
|
||||||
|
@ -161,7 +158,6 @@ class DrupalSaaS(SiteDirective):
|
||||||
name = 'drupal-saas'
|
name = 'drupal-saas'
|
||||||
verbose_name = "Drupdal SaaS"
|
verbose_name = "Drupdal SaaS"
|
||||||
help_text = _("URL path for mounting wordpress multisite.")
|
help_text = _("URL path for mounting wordpress multisite.")
|
||||||
# fpm_listen = settings.WEBAPPS_DRUPALMU_LISTEN
|
|
||||||
group = SiteDirective.SAAS
|
group = SiteDirective.SAAS
|
||||||
regex = r'^/[^ ]*$'
|
regex = r'^/[^ ]*$'
|
||||||
unique_value = True
|
unique_value = True
|
||||||
|
|
Loading…
Reference in New Issue